多态关联允许一个模型同时属于多个其他模型,通过commentable_id和commentable_type字段实现通用关联,适用于评论、图片等跨模型场景。

在Laravel中,多态关联(Polymorphic Relations)允许一个模型同时属于多个其他模型,而无需为每个关联创建单独的外键字段。这种机制非常适合像评论、图片或附件这类可能属于多种类型资源的场景。
什么是多态关联?
举个例子:一篇文章和一个视频都可以有评论。如果不用多态,你需要为文章和视频分别建立两张评论表,或者在评论表中添加article_id和video_id字段。而使用多态,只需要两个字段:commentable_id 和 commentable_type,即可实现通用关联。
数据库结构设计
假设我们有两个模型:Post(文章)和Video(视频),它们都可以拥有多个评论。我们需要创建一个comments表:
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->text('body');
$table->unsignedBigInteger('commentable_id'); // 关联记录的ID
$table->string('commentable_type'); // 关联模型的类名
$table->timestamps();
});
commentable_id保存目标记录的主键值,commentable_type保存目标模型的完整类名(如App\Models\Post)。
定义多态模型关系
在Comment模型中,使用morphTo()方法定义“属于”关系:
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
在Post和Video模型中,使用morphMany()方法定义“拥有多个”关系:
class Post extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
class Video extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
使用多态关联
现在你可以轻松地为文章或视频添加评论:
$post = Post::find(1); $comment = new Comment(['body' => '这是一条评论']); $post->comments()->save($comment); $video = Video::find(1); $comment2 = new Comment(['body' => '这个视频很棒!']); $video->comments()->save($comment2);
读取评论时,也能自动识别所属模型:
$comment = Comment::with('commentable')->first();
echo get_class($comment->commentable); // 输出: App\Models\Post 或 App\Models\Video
你还可以通过多态关系反向查询:
// 获取某篇文章的所有评论 $post->comments; // 获取某个评论所属的内容 $comment->commentable;
基本上就这些。多态关联让Eloquent更灵活,减少重复字段,提升代码复用性。只要记住字段命名规范:{relation}_id 和 {relation}_type,就可以轻松实现跨模型的通用关联。










