Laravel 5.6中如何扩展多态关系至四列字段?
在Laravel中实现双向多态关联(同时关联评论主体与评论者)
完全没问题!Laravel的Eloquent ORM对多态关系的支持相当灵活,默认的*_id+*_type只是约定俗成的命名规则,你完全可以在同一个表中定义两组独立的多态字段——也就是你说的同时关联评论主体和评论发起者的需求。下面是具体的实现方案:
1. 数据库迁移配置
首先确保comments表的迁移文件包含所需的四个字段,同时建议添加索引优化查询性能:
Schema::create('comments', function (Blueprint $table) { $table->id(); // 评论主体的多态字段(关联文章、视频等内容) $table->unsignedBigInteger('commentable_id'); $table->string('commentable_type'); // 评论发起者的多态字段(关联不同类型的用户模型) $table->unsignedBigInteger('commentedby_id'); $table->string('commentedby_type'); $table->text('content'); $table->timestamps(); // 添加复合索引提升关联查询速度 $table->index(['commentable_id', 'commentable_type']); $table->index(['commentedby_id', 'commentedby_type']); });
2. 模型关联定义
在Comment模型中,我们需要定义两个独立的多态关联:
关联评论主体(Commentable)
这个和Laravel默认的多态关联用法一致,因为字段名符合默认命名约定:
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphTo; class Comment extends Model { protected $fillable = ['content', 'commentable_id', 'commentable_type', 'commentedby_id', 'commentedby_type']; // 关联评论的主体(比如文章、视频等模型) public function commentable(): MorphTo { return $this->morphTo(); }
关联评论发起者(CommentedBy)
由于你的字段名是commentedby_id(没有下划线),需要手动指定字段参数让Eloquent识别:
// 关联评论的发起者(比如普通用户、管理员等不同类型的用户模型) public function commentedby(): MorphTo { // 参数依次为:关联名称、type字段名、id字段名 return $this->morphTo(null, 'commentedby_type', 'commentedby_id'); } }
接下来在关联的主体模型(比如Post、Video)中定义反向关联:
// 在Post模型中 public function comments(): MorphMany { return $this->morphMany(Comment::class, 'commentable'); }
在评论发起者模型(比如User、Admin)中定义反向关联:
// 在User模型中 public function authoredComments(): MorphMany { return $this->morphMany(Comment::class, 'commentedby'); } // 若有Admin模型,同样定义反向关联 public function authoredComments(): MorphMany { return $this->morphMany(Comment::class, 'commentedby'); }
3. 实际使用示例
现在就可以正常创建和查询关联数据了:
创建评论
// 从文章模型创建评论,同时指定评论者 $post = Post::find(1); $user = User::find(2); $post->comments()->create([ 'content' => '这是一条测试评论', 'commentedby_id' => $user->id, 'commentedby_type' => get_class($user) ]); // 或者从用户模型创建评论,指定评论主体 $user->authoredComments()->create([ 'content' => '这是另一条测试评论', 'commentable_id' => $post->id, 'commentable_type' => get_class($post) ]);
查询关联数据
// 获取某篇文章的所有评论,同时加载评论作者信息 $post = Post::with('comments.commentedby')->find(1); foreach ($post->comments as $comment) { echo "评论内容:{$comment->content},作者:{$comment->commentedby->name}"; } // 获取某个用户发布的所有评论,同时加载评论对应的内容主体 $user = User::with('authoredComments.commentable')->find(2); foreach ($user->authoredComments as $comment) { echo "评论内容:{$comment->content},评论对象:{$comment->commentable->title}"; }
额外注意事项
- 如果希望自定义
*_type字段存储的内容(比如不用完整类名,改用user、admin这类短标识),可以在对应模型中添加$morphClass属性,例如在User模型中:protected $morphClass = 'user';,Laravel会自动处理映射。 - 确保
*_id字段的类型与关联模型的主键类型一致(比如模型用自增ID的话,字段用unsignedBigInteger)。
内容的提问来源于stack exchange,提问作者aishazafar
相关产品推荐
相关产品推荐

