Laravel

Laravel 模型关系:多态关联

配套视频地址:https://www.bilibili.com/video/av73028135?p=6


多态一对一

项目:运营人员就一个图片,发布一篇博客或者一篇文章。

articles
    id - integer
    title - string

blogs
    id - integer
    title - string

images
    id - integer
    url - string
    imageable_id - integer
    imageable_type - string

模型

# App\Image
public function imageable()
{
    return $this->morphTo();
}

# App\Blog
public function image()
{
    return $this->morphOne('App\Image', 'imageable');
}

# App\Article
public function image()
{
    return $this->morphOne('App\Image', 'imageable');
}

使用

$article = App\Article::find(1);
$image= $article->image;
$articleWithImages = App\Article::with('image')->find(1);
$articlesWithImages = App\Article::with('image')->find([1, 2]);
$image = App\Image::find(1);
$imageable = $image->imageable;

多态一对多

文章可以接受多条评论,视频也可以接受多条评论。

articles
    id - integer
    title - string
    body - text

videos
    id - integer
    title - string
    url - string

comments
    id - integer
    body - text
    commentable_id - integer
    commentable_type - string

模型

# App\Comment
public function commentable()
{
    return $this->morphTo();
}

# App\Video
public function comments()
{
    return $this->morphMany('App\Comment', 'commentable');
}

# App\Article
public function comments()
{
    return $this->morphMany('App\Comment', 'commentable');
}

使用

$article = App\Article::find(1);

foreach ($article->comments as $comment) {
    //
}
$articleWithComments = App\Article::with('comments')->find(1);

$articlesWithComments = App\Article::with('comments')->find([1, 2]);
$comment = App\Comment::find(1);
$commentable = $comment->commentable;

多态多对多

可以给一篇文章打上多个标签。可以给一个视频打上多个标签。

一个标签可以贴在多个文章上面。一个标签也可以贴在多个视频上。

articles
    id - integer
    name - string

videos
    id - integer
    name - string

tags
    id - integer
    name - string

taggables
    tag_id - integer
    taggable_id - integer
    taggable_type - string

模型

# App\Tag
public function articles()
{
    return $this->morphedByMany('App\Article', 'taggable');
}

public function videos()
{
    return $this->morphedByMany('App\Video', 'taggable');
}
# App\Article
public function tags()
{
    return $this->morphToMany('App\Tag', 'taggable');
}

使用

$video = App\Video::find(1);

foreach ($video->tags as $tag) {
    //
}
$tag = App\Tag::find(1);

foreach ($tag->videos as $video) {
    //
}
$videoWithTags = App\Video::with('tags')->find(1);
$videosWithTags = App\Video::with('tags')->find([1, 2]);
$tagWithVideos = App\Tag::with('videos')->find(1);
$tagsWithVideos = App\Tag::with('videos')->find([1, 2]);

定制

# AppServiceProvider
use Illuminate\Database\Eloquent\Relations\Relation;

Relation::morphMap([
    'posts' => 'App\Post',  // posts 是 *_type 字段所存储的值
    'videos' => 'App\Video',
]);

发表评论