murume
murume

Reputation: 310

Eloquent save many to many relation without duplicates

I'm using Laravel 5.5 and have a many to many relationship between products and tags, with a pivot table that has product_id and tag_id as the only two columns.

My models look as follow:

class Product extends Model
{
    public function tags()
    {
        return $this->belongsToMany( 'App\Tag' );
    }
    // other code
}

and

class Tag extends Model
{
    public function product ()
    {
        return $this->belongsToMany( 'App\Product' );
    }

    protected $fillable = [ 'slug' ];
}

The tags table has id, slug and the timestamps columns. I am trying to assign tags that I'm getting from a form in a comma separated string to a product with the code below:

$tags_r = explode( ',', $request->tags );

$tags = [];

foreach ( $tags_r as $tag ) {
    $tags[] = new Tag( [ 'slug' => strtolower( trim( $tag ) ) ] );
}

$p->tags()->saveMany( $tags );

My problem is that when I try to save the tags with no constraint on the tags.slug column, I end up with duplicate tags on several rows. When I set the slug column to unique to avoid duplicates the code throws an error complaining about the constraint. How do I make it so that if a tag exists, it is assigned to a product by use of the pivot table and it is only added as a new row in the tags table if it doesn't already exist?

Upvotes: 4

Views: 4267

Answers (1)

Camilo
Camilo

Reputation: 7184

You can use firstOrCreate() to avoid adding already existing tags into the database.

foreach ( $tags_r as $tag ) {
    $tags[] = Tag::firstOrCreate(['slug' => str_slug($tag)]);
}

$p->tags()->saveMany( $tags );

I also used str_slug() instead of manually creating the slug.

Upvotes: 4

Related Questions