Laravel relationships attach if not already attached Laravel relationships attach if not already attached php php

Laravel relationships attach if not already attached


Laravel has built-in method for this - syncWithoutDetaching:

$message->Users()->syncWithoutDetaching($request->get('users'));


Using syncWithoutDetaching or sync([arr], false) looks cleaner in code, but performs 25x slower than attach(). This is because it checks each id and performs individual database inserts per item.

I'd suggest building upon Paul Spiegel's answer by extending eloquent or creating a new method on your model class.

In my use case I have a Feed class and a Post class linked by a many to many pivot. I added the following method to my Feed class.

public function attachUniquePosts($ids){    $existing_ids = $this->posts()->whereIn('posts.id', $ids)->pluck('posts.id');    $this->posts()->attach($ids->diff($existing_ids));}
  • Attaching 20 posts to a feed using syncWithoutDetaching() took on average0.107s
  • Attaching 20 posts to a feed usingattachUniquePosts() took on average 0.004s


Something like this might work:

Get the IDs that are already attached:

$attachedIds = $message->Users()->whereIn('id', $request->get('users'))->pluck('id');

Remove the attached IDs from the request array:

$newIds = array_diff($request->get('users'), $attachedIds);

Attach the new IDs:

$message->Users()->attach($newIds);