In Laravel, there are no built-in events automatically fired when you attach or detach tags (or any related models) via many-to-many relationships using the `attach()`, `detach()`, or `sync()` methods. However, there are effective ways to trigger custom events when these actions occur.
How to Trigger Custom Events on Attach/Detach of Tags
1. Using Pivot Model Events (Laravel 5.8+)
Starting from Laravel 5.8, you can define a custom Pivot model for your many-to-many relationship and use model events on the pivot model itself. This allows you to listen for `creating`, `created`, `deleting`, and `deleted` events when attaching or detaching:
- Define a custom pivot model class that extends `Illuminate\Database\Eloquent\Relations\Pivot`.
- In your model's relationship method, specify the pivot model using `using()`.
Example:
php
class TaggablePivot extends \Illuminate\Database\Eloquent\Relations\Pivot
{
protected static function boot()
{
parent::boot();
static::created(function ($pivot) {
event(new TagsAttached($pivot));
});
static::deleted(function ($pivot) {
event(new TagsDetached($pivot));
});
}
}
class Post extends Model
{
public function tags()
{
return $this->belongsToMany(Tag::class)->using(TaggablePivot::class);
}
}
With this setup, when you call `$post->tags()->attach($tagId)`, the `created` event on the pivot model fires, and you can handle it in your event listener. Similarly, `detach()` triggers the `deleted` event on the pivot.
2. Manually Dispatching Events After Attach/Detach
If you prefer not to use a custom pivot model, you can manually dispatch events right after calling attach/detach/sync by inspecting the changes returned by `syncWithoutDetaching()` or `sync()`.
Example approach (inspired by Spatie's laravel-tags package discussion):
php
public function attachTags($tags)
{
$tags = collect(Tag::findOrCreate($tags));
$changes = $this->tags()->syncWithoutDetaching($tags->pluck('id')->toArray());
event(new TagsAttached($changes['attached']));
event(new TagsDetached($changes['detached']));
event(new TagsUpdated($changes['updated']));
return $this;
}
Here, after syncing tags without detaching existing ones, you get arrays of attached, detached, and updated IDs. You then fire custom events accordingly. This method gives you control and the ability to batch process these changes.
3. Using Community Packages
There are community packages like `fico7489/laravel-pivot` that add event firing capabilities on pivot attach/detach operations if you want an out-of-the-box solution without custom pivot models.
Summary
- Laravel does not fire attach/detach events by default.
- From Laravel 5.8+, you can use custom Pivot models to hook into pivot model events (`creating`, `created`, `deleting`, `deleted`).
- Alternatively, manually dispatch custom events after attach/detach/sync by analyzing the changes.
- Community packages exist to simplify this.
This approach provides a clean, maintainable way to trigger custom logic when tags are attached or detached in Laravel applications[1][2][5].
Citations:
[1] https://stackoverflow.com/questions/28925292/eloquent-attach-detach-sync-fires-any-event
[2] https://github.com/spatie/laravel-tags/discussions/452
[3] https://laracasts.com/discuss/channels/eloquent/events-on-attach-and-detach
[4] https://spatie.be/docs/laravel-tags/v4/basic-usage/using-tags
[5] https://laravel.io/forum/05-11-2015-how-to-observe-many-to-many-relation-attachsync-action
[6] https://laravel.com/docs/11.x/telescope
[7] https://www.youtube.com/watch?v=6ZBzPz4CfZw
[8] https://laravel.com/docs/11.x/notifications