Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Fireable Laravel Package

envant/fireable

Envant Fireable is a Laravel package that automatically fires events when chosen Eloquent model attributes change. Define fireable fields on a model and react to updates with dedicated events, avoiding manual observer boilerplate and keeping model change handling clean and explicit.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer and let the package's trait do the wiring:

composer require envant/fireable

The first place to look is the package's Fireable trait and its $fireable property contract — that map is the whole API surface. In a model, add the trait and declare which attributes should dispatch which event classes:

use Envant\Fireable\Fireable;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use Fireable;

    protected $fireable = [
        'email' => \App\Events\UserEmailChanged::class,
        'name'  => \App\Events\UserNameChanged::class,
    ];
}

Create ordinary Laravel event classes (they receive the model in the constructor). Then save the model:

$user->email = '[email protected]';
$user->save(); // UserEmailChanged is dispatched

The canonical first use case is an audit trail or notification fan-out: you want "when this column changes, do X" without writing a full observer for every attribute. Start there — one mapped attribute, one listener that writes an audit row — before rolling it out across models.

Implementation Patterns

Attribute-to-event map as the source of truth. Keep the $fireable array adjacent to $fillable/$casts so reviewers can see the model's side effects at a glance. This is the package's main value over hand-written observers: the trigger conditions are declarative and grep-able.

Many attributes → one event. Point several keys at the same event class when a single "profile changed" event makes more sense than per-field events, and inspect $model->getChanges() (or wasChanged('email')) inside the listener to branch. This keeps your event count small and pushes decision logic into listeners where it's testable.

Pair with queued listeners. Keep the model save fast; let listeners implement ShouldQueue for emails, webhooks, or third-party syncs. If you're on Laravel 8+, implement ShouldQueueAfterCommit (or set $afterCommit = true) so listeners don't run against uncommitted data.

Compose with observers, don't replace them. Use Fireable for the "attribute changed" cases and keep observers for lifecycle concerns (created, deleted, restored). If you find yourself mapping 15 attributes, an observer with isDirty() checks is probably clearer.

Testing. Use Event::fake([UserEmailChanged::class]) and Event::assertDispatched() around a save(). Because the package only reacts to dirty attributes, tests should explicitly mutate then save — a factory()->create() will fire every mapped event (see Gotchas), which can silently break unrelated tests.

Integration tip: centralize the "what changed" payload by making your events expose $model and a computed diff, rather than passing raw values. Listeners stay stable if the model gains columns later.

Gotchas and Tips

  • Creation fires everything. On create(), all set attributes are dirty, so every mapped event dispatches. If you only care about updates, guard inside listeners (e.g. if ($model->wasRecentlyCreated) return;) — the package has no built-in "skip on create" flag.
  • No changes, no events. Saving an unmodified model dispatches nothing because nothing is dirty. This is correct but surprising in tests that assert on save() without mutating first.
  • Mass updates bypass it entirely. User::where(...)->update([...]) never hydrates models and never fires model events, so Fireable won't trigger. Same for insert(), upsert(), and raw SQL. Document this for anyone who assumes the events are database-level.
  • saveQuietly() suppresses it. Since the trait rides the model's saved event, saveQuietly() and withoutEvents() silence Fireable too — useful as an escape hatch inside listeners to avoid recursion.
  • Beware recursive saves. A listener that mutates and saves the same model will re-enter the trait. Guard with saveQuietly() or a re-entrancy flag, otherwise you get an infinite loop that only shows up in staging.
  • Dirty detection follows Eloquent semantics. Casts (arrays, JSON, dates) are compared after casting, so mutators that normalize values to the same stored value won't register as dirty. If a change "doesn't fire," dump $model->getDirty() before saving — that's your first debugging step.
  • Transactions and ordering. Events fire during save(), inside any open transaction. Without afterCommit on listeners, a rollback can leave you with dispatched emails for data that never persisted.
  • Version drift. Last release was April 2022 (Laravel 8/9 era). It's a thin trait so it generally keeps working on newer Laravel, but pin it and run your test suite on upgrade — particularly if you rely on ShouldQueueAfterCommit behavior, which is a listener concern rather than the package's.
  • Extension point: because it's a trait, you can override the method that builds the event map (or the dispatch step) in a BaseModel to add conventions like auto-prefixing event namespaces — cheaper than forking the package.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core