附件(Attachment)既然可以作为评论详情(CommentDetail)的配图,也可以作为用户(User)的头像。它们的数据结构如下:
CommentDetail
id - integer
cid - integer
content - text
User
id - integer
name - string
Attachment
id - integer
key - string
AttachmentRelationship
id - integer
target_type - string ('comment_detail' or 'user_avatar')
target_id - integer (User -> id or CommentDetail -> cid)
attachment_key - string
首先,在AppServiceProvider我定义了morphMap:
Relation::morphMap([
'comment_detail' => CommentDetail::class,
'user_avatar' => User::class,
]);
然后,在CommentDetail模型中,定义了获取所有附件的方法:
public function attachments()
{
return $this->morphToMany(
Attachment::class,
"target",
"attachment_relationships",
"target_id",
"attachment_key",
"cid",
"key"
);
}
最后,给一条commentDetail添加附件和关联数据:
$commentDetail = CommentDetail::findOrFail(4);
$attachment = $commentDetail->attachments()->create([
'key' => (string)\Uuid::uuid4(),
]);
在Attachment对应的表中创建的记录是:
id | key |
---|---|
10 | 968e22b8-e4fb-4743-bf08-8ac9cd8ecd56 |
在AttachmentRelationship对应表中的记录却是:
id | target_type | target_id | attachment_key |
---|---|---|---|
1 | comment_detail | 7 | 10 |
我的问题是:AttachmentRelationship中的这条记录的attachment_key字段的值为何不是Attachment中的key字段的值968e22b8-e4fb-4743-bf08-8ac9cd8ecd56而是它id字段的值10? 是关联定义得不对么,要怎么定义?
PS: target_id的7是对应id为4的commentDetail记录中的cid字段的值是正确的。
通过查看源码发现,主动依附关联是使用主键的。
在 Illuminate\Database\EloquentRelations\BelongsToMany 中的create()方法如下:
其中,$instance->getKey()就是获取主键的值。
因此,要实现通过非主键key来关联,分两步走,先手工创建Attachment记录,然后attach($attachmentKey)。要想一步到位它就是使用主键id来关联。
一般来说,一个表的外键使用另一个表的主键是比较主流的做法,Laravel这么做也有一定道理。最终我决定也通过Attachment中的id来关联算了,不使用非主键key来关联。