💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
### [](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)