Laravel maintains a many-to-many relationship in the eloquent ants

I have two models with a many-to-many relationship. I want to be able to set a specific attribute with an array of identifiers and make the connection in the mutator as follows:

<?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 does not work as expected. I get 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, ))

+8
php eloquent laravel
source share
4 answers

You cannot attach many-to-many relationships until you save the model. Call save() on the model before setting up $model->tags , and everything will be fine. The reason for this is that models need to have an identifier that Laravel can put in a pivot table that requires the identifier of both models.

+19
source share

It looks like you are calling the function incorrectly or from an uninitialized model. The error says that profile_id is NULL. Therefore, if you call a function like $profile->setTagsAttribute() , you need to make sure that $ profile is initialized in the database with the identifier.

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

In addition, you can pass an array to the attach function to attach several models at the same time:

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

You can also pass it a model instead of an ID (but a fairly confident array of models won't work)

+3
source share

Try using the synchronization 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 you don't pass. // remove it all together if that is desired. } public function tags() { return $this->belongsToMany('Tag'); } } 
+2
source share

Do not access tags through the tags() function, rather use the tags property. Use the function name if you want to put additional parameters in the relation request and property if you just want to capture tags. tags() works in your getter because you use get() at the end.

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

All Articles