拉拉维尔在雄辩突变体中保存多对多关系


Laravel save many-to-many relationship in Eloquent mutators

我有 2 个具有多对多关系的模型。我希望能够使用id数组设置特定属性,并在突变器中建立这样的关系:

<?php
class Profile extends Eloquent {
    protected $fillable = [ 'name', 'photo', 'tags' ];
    protected $appends = [ 'tags' ];
    public function getTagsAttribute()
    {
        $tag_ids = [];
        $tags = $this->tags()->get([ 'tag_id' ]);
        foreach ($tags as $tag) {
            $tag_ids[] = $tag->tag_id;
        }
        return $tag_ids;
    }
    public function setTagsAttribute($tag_ids)
    {
        foreach ($tag_ids as $tag_id) {
            $this->tags()->attach($tag_id);
        }
    }
    public function tags()
    {
        return $this->belongsToMany('Tag');
    }
}
<?php
class Tag extends Eloquent {
    protected $fillable = [ 'title' ];
    protected $appends = [ 'profiles' ];
    public function getProfilesAttribute()
    {
        $profile_ids = [];
        $profiles = $this->profiles()->get([ 'profile_id' ]);
        foreach ($profiles as $profile) {
            $profile_ids[] = $profile->profile_id;
        }
        return $profile_ids;
    }
    public function profiles()
    {
        return $this->belongsToMany('Profile');
    }
}

但是,setTagsAttribute函数未按预期工作。我收到以下错误:SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'profile_id' cannot be null (SQL: insert into profile_tag ( profile_id , tag_id ) values (?, ?)) (Bindings: array ( 0 => NULL, 1 => 1, ))

保存模型之前,无法附加多对多关系。在设置$model->tags之前调用模型上的save(),您应该没问题。这样做的原因是模型需要有一个 Laravel可以放入数据透视表中的 ID,该 ID 需要两个模型的 ID。

看起来您调用了不正确的函数或从未初始化的模型中调用了该函数。错误指出profile_id为 NULL。因此,如果要按$profile->setTagsAttribute()调用函数,则需要确保使用 ID 在数据库中初始化$profile。

$profile = new Profile;
//will fail because $profile->id is NULL
//INSERT: profile->save() or Profile::Create();
$profile->setTagsAttribute(array(1,2,3));  

此外,您可以将数组传递给 attach 函数以一次附加多个模型,如下所示:

$this->tags()->attach($tag_ids);

您也可以将模型而不是ID传递给它(但可以肯定的是,模型数组不起作用(

尝试使用同步方法:

class Profile extends Eloquent {
    protected $fillable = [ 'name', 'photo', 'tags' ];
    protected $appends = [ 'tags' ];
    public function getTagsAttribute()
    {
        return $this->tags()->lists('tag_id');
    }
    public function setTagsAttribute($tag_ids)
    {
        $this->tags()->sync($tagIds, false);
        // false tells sync not to remove tags whose id's you don't pass.
        // remove it all together if that is desired.
    }
    public function tags()
    {
        return $this->belongsToMany('Tag');
    }
}

不要通过 tags() 函数访问标记,而是使用 tags 属性。如果要将其他参数弹出到关系查询上,请使用函数名称,如果只想获取标记,请使用属性。 tags()在您的吸气器中起作用,因为您最后使用的是get()

public function setTagsAttribute($tagIds)
{
    foreach ($tagIds as $tagId)
    {
        $this->tags->attach($tagId);
    }
}