Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel save many-to-many relationship in Eloquent mutators

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:

<?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 intoprofile_tag(profile_id,tag_id) values (?, ?)) (Bindings: array ( 0 => NULL, 1 => 1, ))

like image 546
Jon Koops Avatar asked Dec 02 '13 23:12

Jon Koops


2 Answers

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.

like image 115
Andreas Avatar answered Nov 15 '22 18:11

Andreas


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 = 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:

$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)

like image 24
TonyArra Avatar answered Nov 15 '22 18:11

TonyArra