Laravel在Eloquent mutators中保存了多对多的关系

时间:2013-12-02 23:41:32

标签: php laravel eloquent

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

<?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, ))

4 个答案:

答案 0 :(得分:20)

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

答案 1 :(得分:3)

看起来您正在错误地调用函数或从未初始化的模型调用函数。该错误表明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(但很可靠的模型数组不起作用)

答案 2 :(得分:2)

尝试使用同步方法:

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');
    }

}

答案 3 :(得分:-1)

请勿通过tags()功能访问代码,而应使用tags属性。如果要在关系查询和属性上弹出其他参数(如果只想抓取标记),请使用函数名称。 tags()适用于您的getter,因为您最终会使用get()

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