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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20340097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 08:43:38  来源:igfitidea点击:

Laravel save many-to-many relationship in Eloquent mutators

phplaraveleloquent

提问by Jon Koops

I've got 2 models with a many-to-many relationship. I want to be able to set a specific attribute with an array of ids and make the relationship in the mutator like this:

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

}

However the setTagsAttributefunction isn't working as expected. I'm getting the following error: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'profile_id' cannot be null (SQL: insert intoprofile_tag(profile_id,tag_id) values (?, ?)) (Bindings: array ( 0 => NULL, 1 => 1, ))

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

回答by Andreas

You can't attach many-to-many relations until you've saved the model. Call save()on the model before setting $model->tagsand you should be OK. The reason for this is that the model needs to have an ID that Laravel can put in the pivot table, which needs the ID of both models.

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

回答by TonyArra

It looks like you're calling the function incorrectly or from an uninitialized model. The error says that profile_id is NULL. So if you're calling the function as $profile->setTagsAttribute()you need to make sure that $profile is initialized in the database with an ID.

看起来您正在错误地调用该函数或从未初始化的模型中调用该函数。错误表明 profile_id 为 NULL。因此,如果您根据需要调用该函数,$profile->setTagsAttribute()请确保 $profile 在数据库中使用 ID 进行初始化。

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

Additionally, you can pass an array to the attach function to attach multiple models at once, like so:

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

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

You can also pass it the model instead of the ID (but pretty sure array of models won't work)

您也可以将模型而不是 ID 传递给它(但很确定模型数组不起作用)

回答by William Cahill-Manley

Try using the sync method:

尝试使用同步方法:

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

}

回答by Dwight

Don't access the tags through the tags()function, rather use the tagsproperty. Use the function name if you want to pop additional parameters onto the relationship query and the property if you just want to grab the tags. tags()works in your getter because you're using get()on the end.

不要通过tags()函数访问标签,而是使用tags属性。如果您想在关系查询中弹出附加参数,请使用函数名称,如果您只想获取标签,请使用该属性。tags()在你的吸气剂中工作,因为你get()最终使用。

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