NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Listen for these events to extend behaviour — audit logs, search re-indexing, syncing to other systems. All live in RoundlyConsulting\Attributes\Events:

EventPropertiesDispatched by
AttributeAttachedowner, attributeEvery value or meta write: set(), setMany(), stage()->save() and meta() (and their model methods) — and once per value in sync().
AttributeDetachedowner, nameforget(), forgetExcept() and the extras sync() drops (and their model methods) — once per name that was actually attached.
AttributesSyncedowner, attributessync(), stage()->sync() and syncAttributes(), after every value is attached. attributes is a list<AttributeData>.
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Attributes\Events\AttributeAttached;
use RoundlyConsulting\Attributes\Events\AttributeDetached;
use RoundlyConsulting\Attributes\Events\AttributesSynced;

Event::listen(function (AttributeAttached $event): void {
    $event->owner;              // the model the attribute belongs to
    $event->attribute->name;    // 'color'
    $event->attribute->value;   // typed value
});

Event::listen(function (AttributeDetached $event): void {
    $event->owner;
    $event->name;               // 'color'
});

Event::listen(function (AttributesSynced $event): void {
    $event->owner;
    $event->attributes;         // list<AttributeData>: ->name, ->value, ->meta
});

Events are dispatched once the write’s transaction commits (they implement ShouldDispatchAfterCommit), so a rolled-back write never announces itself — and a value that fails strict mode, validation or a uniqueness check dispatches nothing.

A listener class

Type-hint the event in a listener’s handle() method and Laravel’s event discovery wires it up:

namespace App\Listeners;

use App\Models\Product;
use RoundlyConsulting\Attributes\Events\AttributeAttached;

final class ReindexProductOnAttributeChange
{
    public function handle(AttributeAttached $event): void
    {
        if (! $event->owner instanceof Product) {
            return;
        }

        // re-index $event->owner in your search engine
    }
}

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 crypto

By 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.