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 using
attachUniquePosts()
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);