### [](https://octobercms.com/docs/database/relations#polymorphic-relations)多态关系
多态关系允许一个模型在单个关联上属于多个以上的模型。
### [](https://octobercms.com/docs/database/relations#one-to-one-polymorphic-relations)一对一
#### 表结构
一对一的多态关系类似于简单的一对一关系。但是,目标模型可以在单个关联上属于一种以上类型的模型。例如,假设您要存储员工和产品的照片。使用多态关系,您可以`photos`在这两种情况下使用一个表。首先,让我们检查建立这种关系所需的表结构:
~~~
staff
id - integer
name - string
products
id - integer
price - integer
photos
id - integer
path - string
imageable_id - integer
imageable_type - string
~~~
需要注意的两个重要列是表中的`imageable_id`和`imageable_type`列`photos`。该`imageable_id`列将包含拥有人员或产品的ID值,而该`imageable_type`列将包含拥有模型的类名。该`imageable_type`列是ORM如何确定访问该`imageable`关系时要返回的拥有模型的“类型”。
#### 模型结构
接下来,让我们检查建立这种关系所需的模型定义:
~~~
class Photo extends Model
{
public $morphTo = [
'imageable' => []
];
}
class Staff extends Model
{
public $morphOne = [
'photo' => ['Acme\Blog\Models\Photo', 'name' => 'imageable']
];
}
class Product extends Model
{
public $morphOne = [
'photo' => ['Acme\Blog\Models\Photo', 'name' => 'imageable']
];
}
~~~
#### 检索多态关系
定义数据库表和模型后,您可以通过模型访问关系。例如,要访问工作人员的照片,我们可以简单地使用`photo`dynamic属性:
~~~
$staff = Staff::find(1);
$photo = $staff->photo
~~~
您还可以通过访问`morphTo`关系名称来从多态模型中检索该多态关系的所有者。在我们的例子中,这就是模型的`imageable`定义`Photo`。因此,我们将其作为动态属性进行访问:
~~~
$photo = Photo::find(1);
$imageable = $photo->imageable;
~~~
在`imageable`对关系`Photo`模式将返回一个`Staff`或`Product`实例,这取决于模型的类型拥有的照片。
### [](https://octobercms.com/docs/database/relations#one-to-many-polymorphic-relations)一对多
#### 表结构
一对多多态关系类似于简单的一对多关系。但是,目标模型可以在单个关联上属于一种以上类型的模型。例如,假设您的应用程序的用户可以“评论”帖子和视频。使用多态关系,您可以`comments`在这两种情况下使用一个表。首先,让我们检查建立这种关系所需的表结构:
~~~
posts
id - integer
title - string
body - text
videos
id - integer
title - string
url - string
comments
id - integer
body - text
commentable_id - integer
commentable_type - string
~~~
#### 模型结构
接下来,让我们检查建立这种关系所需的模型定义:
~~~
class Comment extends Model
{
public $morphTo = [
'commentable' => []
];
}
class Post extends Model
{
public $morphMany = [
'comments' => ['Acme\Blog\Models\Comment', 'name' => 'commentable']
];
}
class Product extends Model
{
public $morphMany = [
'comments' => ['Acme\Blog\Models\Comment', 'name' => 'commentable']
];
}
~~~
#### 检索关系
定义数据库表和模型后,您可以通过模型访问关系。例如,要访问帖子的所有评论,我们可以使用`comments`dynamic属性:
~~~
$post = Author\Plugin\Models\Post::find(1);
foreach ($post->comments as $comment) {
//
}
~~~
您还可以通过访问`morphTo`关系名称来从多态模型中检索该多态关系的所有者。在我们的例子中,这就是模型的`commentable`定义`Comment`。因此,我们将其作为动态属性进行访问:
~~~
$comment = Author\Plugin\Models\Comment::find(1);
$commentable = $comment->commentable;
~~~
在`commentable`对关系`Comment`模式将返回一个`Post`或`Video`实例,这取决于模型的类型拥有评论。
您还可以通过将属性设置为`morphTo`关系的名称(在本例中为)来更新相关模型的所有者`commentable`。
~~~
$comment = Author\Plugin\Models\Comment::find(1);
$video = Author\Plugin\Models\Video::find(1);
$comment->commentable = $video;
$comment->save()
~~~
### [](https://octobercms.com/docs/database/relations#many-to-many-polymorphic-relations)多对多
#### 表结构
除了“一对一”和“一对多”关系外,您还可以定义“多对多”多态关系。例如,博客`Post`和`Video`模型可以共享与模型的多态关系`Tag`。使用多对多多态关系使您可以拥有一个唯一标签列表,该列表在博客文章和视频之间共享。首先,让我们检查表结构:
~~~
posts
id - integer
name - string
videos
id - integer
name - string
tags
id - integer
name - string
taggables
tag_id - integer
taggable_id - integer
taggable_type - string
~~~
#### 模型结构
接下来,我们准备在模型上定义关系。在`Post`和`Video`车型都将有一个`tags`在定义的关系`$morphToMany`上基本模型类属性:
~~~
class Post extends Model
{
public $morphToMany = [
'tags' => ['Acme\Blog\Models\Tag', 'name' => 'taggable']
];
}
~~~
#### 定义关系的逆关系
接下来,在`Tag`模型上,您应该为其每个相关模型定义一个关系。因此,对于此示例,我们将定义一个`posts`关系和一个`videos`关系:
~~~
class Tag extends Model
{
public $morphedByMany = [
'posts' => ['Acme\Blog\Models\Post', 'name' => 'taggable'],
'videos' => ['Acme\Blog\Models\Video', 'name' => 'taggable']
];
}
~~~
#### 检索关系
定义数据库表和模型后,您可以通过模型访问关系。例如,要访问帖子的所有标签,您可以简单地使用`tags`dynamic属性:
~~~
$post = Post::find(1);
foreach ($post->tags as $tag) {
//
}
~~~
您还可以通过访问`$morphedByMany`属性中定义的关系的名称,从多态模型中检索多态关系的所有者。在我们的案例中,这就是模型上的`posts`或`videos`方法`Tag`。因此,您将这些关系作为动态属性进行访问:
~~~
$tag = Tag::find(1);
foreach ($tag->videos as $video) {
//
}
~~~
#### [](https://octobercms.com/docs/database/relations#custom-polymorphic-types)自定义多态类型
默认情况下,完全限定的类名用于存储相关的模型类型。例如,给定上面的示例,其中a`Photo`可能属于`Staff`或a`Product`,则默认`imageable_type`值分别为`Acme\Blog\Models\Staff`或`Acme\Blog\Models\Product`。
使用自定义多态类型可以使数据库与应用程序的内部结构脱钩。您可以定义一个关系“变形图”以为每个模型提供一个自定义名称,而不是类名称:
~~~
use October\Rain\Database\Relations\Relation;
Relation::morphMap([
'staff' => 'Acme\Blog\Models\Staff',
'product' => 'Acme\Blog\Models\Product',
]);
~~~
`morphMap`在[插件注册文件](https://octobercms.com/docs/plugin/registration#registration-methods)的`boot`方法中最常见的注册位置。[](https://octobercms.com/docs/plugin/registration#registration-methods)
- 基本说明
- 基本操作
- October cms 安装
- 后台控制器路径
- 图标
- 获取安装网上的插件/主题
- 插件构造器使用
- 定时任务
- October后台控制器
- vscode编辑器
- ajax操作
- 使用
- ajax更新组件
- ajax属性API
- JavaScript API
- ajax综合使用
- 主题
- 多语言主题
- 安装市场主题
- 主题程序处理
- 主题
- 页面
- 部件
- 布局
- 内容
- 组件
- 媒体
- 主题表单操作
- 表单使用
- 表单后端程序处理
- 插件
- 自定义插件
- 插件说明
- 插件导航条
- 插件数据库设置
- 插件的设置管理
- 插件的配置文件config
- 组件
- app服务
- app容器
- 扩展行为
- 缓存
- Collection类
- Lazy Collections
- Collection方法
- 助手函数
- 数组助手函数
- 路径助手函数
- 玄乐助手函数
- 其他助手函数
- 错误与记录
- 事件处理
- HTML页面
- 文件与目录操作
- 散列和加密
- 邮件
- 邮件内容
- 邮件发送
- 分页
- 模板解析器
- 动态解析器语法
- 队列消息
- 请求与输入
- 响应
- 视图
- 路由器
- 配置
- 验证操作
- 处理错误消息
- 错误消息与视图
- 可用的验证规则
- 有条件的验证规则
- 验证数组
- 错误消息
- 自定义验证规则
- 模型操作
- 定义模型与其属性
- 检索模型
- 插入与更新
- 删除模型
- 查询范围
- 事件操作
- 关联操作
- 定义关系
- 关系类型
- 多肽关系
- 关系查询
- 渴望加载
- 插入模型
- 数据库操作
- 基本用法
- 数据表结构
- 查询连贯操作
- 结果检索
- select子句
- 插入更新
- where子句
- 排序,分组,限制和偏移
- 文件附件
- Collection操作
- 属性操作
- 系列化json
- 数据库属性
- 数据库行为
- 控制器
- 后台控制器定义
- 后台页面
- 后台组件
- 后台表单
- 表单组件
- 表单视图
- 表单行为
- 后台列表
- 列表行为
- 列表过滤器
- 可用列类型
- 关系行为
- 关系行为类型
- 扩展关系行为
- 列表排序操作
- 导入导出操作
- 用于与权限
- corlate模板修改
- 修改顶部导航
- laravel问题
- 控制器不存在
- 控制器
- 路由组
- laravel笔记
- laravel 安装
- 伪静态配置
- 依赖注入 & 控制器
- 中间件
- 路由文件
- 视图