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.
Architecture fit. Fireable is a thin, single-purpose extension to Eloquent's save lifecycle: a trait plus an attribute-to-event-class map declared on the model, which inspects changed attributes on save and dispatches the mapped Laravel events. It slots into the existing event/observer architecture rather than competing with it, and it reinforces a pattern most Laravel codebases already drift toward — domain events derived from state change. There is no service provider sprawl, no persistence layer, no schema footprint. For a modular monolith or a DDD-lite bounded-context design, this is a reasonable, low-ceremony primitive.
Integration feasibility. High. Adoption is Composer install, use Fireable on a model, declare the map, and write ordinary event classes and listeners. No migrations, no config publishing required for basic use, no changes to call sites. A competent Laravel developer can spike this in under a day.
Technical risk. Concentrated in three areas. First, staleness: the last release is April 2022, which predates several Laravel majors, so Composer constraints and PHP 8.2/8.3 compatibility are unverified and are the single largest adoption blocker. Second, implicit semantics: correctness depends on whether change detection uses dirty attributes, post-save changes, or wasChanged(), and whether it honors saveQuietly(), withoutEvents(), and bulk Model::where()->update() (which bypasses model events entirely). Third, bus factor: a single maintainer and a small, largely undocumented surface area. Mitigating all three is cheap because the package is small — the realistic plan is to treat it as vendored source, not as a dependency you rely on upstream for.
Key questions. Does the current release install cleanly on our target Laravel and PHP versions? Does it fire on model creation, or only updates? One event per changed attribute or one aggregate event per save? How are casts handled — enums, JSON/array columns, dates, encrypted attributes? Does it fire on created/saved and in what order relative to registered observers? Are events dispatched synchronously, and are listeners expected to be queued by the consumer? What happens under saveQuietly() and inside a transaction that rolls back? What is the maintainer's stated support policy?
Stack fit. Native to Laravel/Eloquent; composes with observers, queued listeners, broadcasting, and transactional event dispatch. Nothing in the package presumes a specific app architecture, so it fits greenfield and brownfield equally. The low opportunity score (0.38) is a signal worth heeding: this is a convenience wrapper, not a platform bet — value comes from consistency, not capability.
Migration path. Purely additive. Do not rip out observers or ad-hoc Event::dispatch calls up front. Adopt per model, starting with a low-blast-radius domain, and leave existing observers in place until the new events are proven. Where an observer already exists for the same attribute, retire it only after the listener parity is covered by tests. Wrap the trait in a project-owned base trait so the package can be swapped for an in-house implementation without touching domain models.
Compatibility. Pin an exact version, and run a compatibility spike before any commitment. If upstream constraints block our Laravel version, fork under our org, apply the constraint and typing fixes, and reference it via a VCS or path repository — a few hours of work for a package this size. Add a composer outdated-style check to the periodic dependency review so the fork does not silently rot.
Sequencing. (1) Compatibility spike on a throwaway branch with a representative model, including enum/JSON casts and a bulk update. (2) Write integration tests asserting exactly which events fire, with what payload, and which do not fire on bulk/quiet paths. (3) Roll out to one bounded context, with listeners queue-backed. (4) Instrument dispatch and add dashboards before expanding. (5) Make an explicit build-vs-buy call at the second or third model — the package's surface is small enough that internalizing it may be the lower-risk endpoint.
Maintenance. Upstream is dormant, but the artifact is small and MIT-licensed, so the real cost is a periodic framework-compatibility audit at each Laravel major, not ongoing patching. Budget a named owner and a few hours per upgrade cycle. The fork-and-maintain path is realistic here in a way it would not be for a large dependency.
Support. Community-only, no SLA, 442 stars, effectively one maintainer. There is no escalation path except reading the source. That is acceptable for a leaf-level convenience package and unacceptable for anything on the critical payment or auth path without local ownership.
Scaling. Runtime overhead is negligible — a handful of dirty-attribute comparisons per save. The scaling concern is entirely downstream: event fan-out per save, listener volume, synchronous listeners doing I/O, and batch jobs that save thousands of models and would otherwise be silent. Keep listeners queued and idempotent.
Failure modes. The dangerous one is silent non-firing — bulk updates, saveQuietly(), framework upgrades that break the trait, or an attribute map typo all cause business logic to be skipped with no error. Secondary modes: duplicate dispatch on job retries, ordering conflicts with existing observers, recursion when a listener saves the model again, and events dispatched inside transactions that later roll back. Each needs an explicit test and, for the first, a monitoring signal (compare expected versus observed dispatch counts on core models).
Ramp-up. Near-zero syntactically — an array on a model and a trait — so onboarding is measured in minutes. The real ramp-up cost is the unstated semantics: engineers will assume events fire in cases where they do not. Write a one-page internal contract describing when events fire and when they do not, and make it the required reading for anyone adding a model to the map.
How can I help you explore Laravel packages today?