Php 拉雷维尔在雄辩的变异中保存了多对多关系

Php 拉雷维尔在雄辩的变异中保存了多对多关系,php,laravel,eloquent,Php,Laravel,Eloquent,我有两个具有多对多关系的模型。我希望能够使用ID数组设置特定属性,并使mutator中的关系如下所示: <?php class Profile extends Eloquent { protected $fillable = [ 'name', 'photo', 'tags' ]; protected $appends = [ 'tags' ]; public function getTagsAttribute() { $tag_ids

我有两个具有多对多关系的模型。我希望能够使用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');
    }

}

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

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

尝试使用同步方法:

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

}

看起来您调用的函数不正确或来自未初始化的模型。错误表明profile_id为空。因此,如果您以
$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));  
此外,还可以将数组传递给“附加”函数,以便一次附加多个模型,如下所示:

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

您还可以将模型而不是ID传递给它(但非常确定模型数组不会工作)

在保存模型之前,您不能附加多对多关系。在设置
$model->tags
之前,在模型上调用
save()
,您应该可以了。这是因为该模型需要一个ID,Laravel可以将该ID放入pivot表中,pivot表需要两个模型的ID。

我尝试过这个方法,但我得到了以下错误:
调用非对象上的成员函数attach()
运行查询时需要括号。该属性等同于检索关系,但不用于运行查询。请参阅不确定您正在使用的Laravel版本…sync似乎未使用第二个参数:。这将从透视表中删除所有其他ID。@TonyArra sync在4.0.6或4个月前收到第二个参数has。具体变化发生在六个月前很明显,在这种情况下api文档已经过时了。啊,我明白了。我希望我可以使用mutator函数来设置模型上的关系,而不必一直手动编写代码。