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
Laravel save many-to-many relationship in Eloquent mutators
提问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 setTagsAttribute
function 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 into
profile_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 into
profile_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->tags
and 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 tags
property. 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);
}
}