猿问

Laravel morphToMany 关联在保存时关联表记录不对

附件(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字段的值是正确的。

慕斯709654
浏览 754回答 1
1回答

SMILET

通过查看源码发现,主动依附关联是使用主键的。 在 Illuminate\Database\EloquentRelations\BelongsToMany 中的create()方法如下: public function create(array $attributes = [], array $joining = [], $touch = true) { $instance = $this->related->newInstance($attributes); // Once we save the related model, we need to attach it to the base model via // through intermediate table so we'll use the existing "attach" method to // accomplish this which will insert the record and any more attributes. $instance->save(['touch' => false]); $this->attach($instance->getKey(), $joining, $touch); return $instance; } 其中,$instance->getKey()就是获取主键的值。 因此,要实现通过非主键key来关联,分两步走,先手工创建Attachment记录,然后attach($attachmentKey)。要想一步到位它就是使用主键id来关联。 一般来说,一个表的外键使用另一个表的主键是比较主流的做法,Laravel这么做也有一定道理。最终我决定也通过Attachment中的id来关联算了,不使用非主键key来关联。
随时随地看视频慕课网APP
我要回答