chelout/laravel-relationship-events
Adds the missing relationship events to Laravel Eloquent models. Traits for hasOne, belongsTo, hasMany, belongsToMany, morphOne, morphTo, morphMany, morphToMany, and morphedByMany let you listen for saved, updated, attached, detached, and other events, useful for cache invalidation and audit logs.
Feature scoping: side-effects on relationship changes. This package closes a well-known gap in Eloquent: model events fire when a model is saved, but not when related records are attached, detached, synced, toggled, associated, or created through a relationship. If any roadmap item depends on "when X gets linked to Y, do Z," this is the enabling primitive. Concretely:
belongsToManyAttached/Detached) rather than polling or duplicating logic at every call site.attach/detach/sync fidelity; missed detaches are silent revenue leakage.Build vs. buy. Building this in-house is deceptively expensive: nine relationship types × their create/save/update/attach/detach/sync/toggle/associate/dissociate variants, plus observer integration and dispatchable event classes. That's weeks of edge-case work that has nothing to do with your differentiator. Adopting an MIT package at ~500 stars converts an engineering project into a composer line — a favorable trade if the risk posture below is acceptable.
Architecture decision: centralize cross-cutting side-effects in the model layer vs. a service/repository layer. Adopting this package is an implicit vote for "model events are our side-effect bus." That's a real architectural commitment; make it deliberately rather than by default.
Roadmap signal. The package tracks Laravel majors closely (v5.x ↔ Laravel 13 / PHP 8.3, v4.x ↔ 12.x, v3.x ↔ 11.x). That cadence is the single best indicator that it will survive your next framework upgrade cycle.
Adopt when:
v3/v4/v5), keeping upgrade lag predictable.boot() or in standard Laravel observers (this package registers them as first-class observers, which keeps the team's existing mental model intact).morphMany, morphToMany, morphedByMany — which most audit packages handle poorly or not at all.detach and update on hasMany), so this is not free at high throughput.Look elsewhere or build narrower when:
0 recorded dependents) and a self-declared "Tests, tests, tests" to-do. Treat it as community tooling, not infrastructure you can escalate.DB::table()->insert(), raw SQL, queue-based replication, or an external system writing to the pivot table will never fire these events. If that's your reality, events are the wrong abstraction — look at database triggers or CDC.spatie/laravel-activitylog or owen-it/laravel-auditing plus custom pivot models may suffice with less surface area.Mitigation checklist before shipping to production:
For executives (60 seconds): We have a recurring class of bugs where something changes in a relationship — a role is granted, a tag is removed, a team member leaves — and downstream systems don't find out. Audit logs miss it, caches go stale, billing seat counts drift. The usual fix is engineering work duplicated in every place that touches those relationships, which is exactly where bugs hide. This package, chelout/laravel-relationship-events, is a free, MIT-licensed, drop-in that makes those events first-class in our stack. It's a few lines of configuration, roughly zero cost, and it retires a whole category of "why didn't anything happen?" defects. The one caveat we manage deliberately: it's a small open-source project with a single maintainer, so we pin the version and keep it behind our own thin abstraction — meaning if we ever need to replace it, that's an afternoon, not a quarter.
For engineering: It gives us pre/post events across one-to-one, one-to-many, many-to-many, has-many-through, and all three polymorphic variants — attaching/attached, syncing/synced, saving/saved, associating/associated, and so on. It plugs into standard Laravel observers and supports $dispatchesEvents for class-based events, so it fits our existing patterns rather than inventing a new one. Two things to internalize: some events fire additional queries (detach, hasMany::update), so it belongs on domain operations, not hot loops; and nothing fires for writes that bypass Eloquent, so bulk operations still need explicit handling. Plan to own the integration tests for the relations we actually use.
For the sponsoring product area: The customer-visible payoff is reliability — audit entries that are always complete, notifications that always fire, permission changes that take effect immediately without cache-staleness lag. It's a small, reversible investment that makes several roadmap items cheaper to build, because "when this relationship changes" becomes a one-line hook instead of a new service.
How can I help you explore Laravel packages today?