鍍金池/ 問答/PHP/ Laravel morphToMany 關聯(lián)在保存時關聯(lián)表記錄不對

Laravel morphToMany 關聯(lián)在保存時關聯(lián)表記錄不對

附件(Attachment)既然可以作為評論詳情(CommentDetail)的配圖,也可以作為用戶(User)的頭像。它們的數(shù)據(jù)結構如下:

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添加附件和關聯(lián)數(shù)據(jù):

$commentDetail = CommentDetail::findOrFail(4);
$attachment = $commentDetail->attachments()->create([
    'key' => (string)\Uuid::uuid4(),
]);

在Attachment對應的表中創(chuàng)建的記錄是:

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? 是關聯(lián)定義得不對么,要怎么定義?

PS: target_id的7是對應id為4的commentDetail記錄中的cid字段的值是正確的。

回答
編輯回答
話寡

通過查看源碼發(fā)現(xiàn),主動依附關聯(lián)是使用主鍵的。

在 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()就是獲取主鍵的值。

因此,要實現(xiàn)通過非主鍵key來關聯(lián),分兩步走,先手工創(chuàng)建Attachment記錄,然后attach($attachmentKey)。要想一步到位它就是使用主鍵id來關聯(lián)。

一般來說,一個表的外鍵使用另一個表的主鍵是比較主流的做法,Laravel這么做也有一定道理。最終我決定也通過Attachment中的id來關聯(lián)算了,不使用非主鍵key來關聯(lián)。

2017年3月31日 06:22