Every event is a final readonly class in RoundlyConsulting\Tags\Events implementing ShouldDispatchAfterCommit — it fires only once the change committed, never for a rollback:
| Event | Payload | Fires when |
|---|---|---|
Tagged | taggable, tags | Tags were attached to a model (attach or sync) — only when something changed. |
Untagged | taggable, tags | Tags were detached (detach, sync, clear, a force-deleted taggable) — only when something changed. |
TagCreated | tag | A tag was created — through the catalog, or for a new free-form name while tagging. |
TagUpdated | tag, changed | Name, description, slug, colour or icon changed; changed lists which. |
TagMoved | tag, from, to | A new parent or a new position; from / to are the old and new parent (null: root). |
TagsReordered | type, parent, tags | Siblings under a parent (the roots when null) were reordered; tags in their new order. |
TagDeleted | tag, detached, subtree | A tag (and with TagChildren::Delete its subtree) was deleted and detached everywhere; detached counts the taggings removed. No per-model Untagged fires. |
TagRestored | tag | A deleted tag came back — restore(), or a create, findOrCreate, attach or sync of a name it held. It carries no taggings. |
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Tags\Events\TagDeleted;
use RoundlyConsulting\Tags\Events\Tagged;
use RoundlyConsulting\Tags\Events\Untagged;
Event::listen(function (Tagged $event): void {
// $event->taggable — the model; $event->tags — list<Tag> this write attached
});
Event::listen(function (Untagged $event): void {
// $event->tags — list<Tag> this write detached (a detach, a sync, a clear, a force delete)
});
// A deleted tag fires no per-model Untagged: react to it once, here
Event::listen(function (TagDeleted $event): void {
// $event->tag, $event->detached (taggings removed), $event->subtree (tags deleted with it)
});- Tagged and Untagged fire once per write, with every tag it attached or detached — never for a call that changed nothing.
- A tag deleted through the catalog detaches it everywhere in one statement and fires one TagDeleted, not an Untagged per model.
- Tags::fake() does not fake events — every call still runs — so Event::fake() works next to it.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.