简介
博客系统架构众所周知,眼前看的就是,最基础的应该有那些熟悉?有标题,有内容,并且能知道是谁发布的,并且用户可以对该博客进行评论,这就够了
所以我们可以得出,需要有用户表User 博客表Blog 评论表Comment,本篇文章以Blog与Comment之间的多态关联举例,描述Laravel多态关联的妙用
表结构设计
最简单的表结构可能是这样的:
Blog:
id
title
body
Comment:
id
body
blog_id //用于指向博客
可这样就遇到了一个问题,以后可能还开发新闻功能,新闻也可以评论,这样就需要改表结构:
Comment:
id
body
blog_id
article_id
如果再出现视频、动态等一系列可评论的模块,那评论表的冗余字段就太多了
Comment:
id
body
blog_id
article_id
video_id
xxx_id
...
重点来了
Laravel给的解决方案是这样的:
Comment:
id
user_id
body
commentable_id //关联对象ID
commentable_type //关联对象类型
这样就能够使用同一张Comment
表对各个模块进行评论–>多态关联
实现
Comment
表和Blog
表的设计结构如下:
Blog:
id
title
body
Comment:
id
body
commentable_id
commentable_type
可使用以下命令创建模型和数据迁移
php artisan make:model blog -m
php artisan make:model comment -m
创建表(排除与本文章无关的数据)
Schema::create('blogs', function (Blueprint $table) {
$table->increments('id');
$table->string('title')->comment('标题');
$table->longtext('body')->comment('内容');
});
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->morphs('commentable');
$table->text('body')->comment('内容');
});
定义关系
Comment
是多态多对一,使用morphTo
方法:
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
Blog
对Comment
为一对多,且为多态关联,使用morphMany
方法:
class Blog extends Model
{
public function comments()
{
return $this->morphMany(\App\Comment::class, 'commentable');
}
}
这样关系已定义完成,但无法使用,需要在AppServiceProvider
中定义多态关联的字段:
public function boot()
{
Relation::morphMap([
'blog' => Blog::class,
]);
}
这样多态关联就定义完成了
效果
Blog
可通过comments
取到关联的评论内容
Comment
也可通过commentable
取到与之关联的博客
例如:
Blog::find(3)->comments()
或
Blog::with('comments')->find(3)