signifly/laravel-pivot-events
Laravel package that fires Eloquent model events for pivot tables on many-to-many relationships. It dispatches attaching, attached, detaching, detached, updating, updated, saving, and saved events, letting you hook into sync, attach, and detach operations without custom code.
Architecture fit
BelongsToMany relationship layer: it fills the well-known gap where attach(), detach(), sync(), and updateExistingPivot() mutate the pivot table without dispatching model events.->using(MyPivot::class)), which participate in Eloquent's standard created/updated/deleted event lifecycle.Integration feasibility
composer require, add the trait(s) to the relevant models, register listeners. A developer-day, not a sprint.attach, detach, sync, syncWithoutDetaching, toggle, updateExistingPivot, and bulk array forms of each.illuminate/* version range actually admits your Laravel version rather than resolving with a warning.Technical risk — High
| Risk | Severity | Rationale |
|---|---|---|
| Abandonment | High | Archived upstream; no patches, no security triage, no Laravel-major compatibility work |
| Framework-internal coupling | High | Requires overriding BelongsToMany/Pivot resolution — the exact surface Laravel refactors across majors |
| Silent failure mode | High | If the hook stops binding, events simply don't fire. No exception, no log. Audit trails and downstream consumers degrade invisibly |
| Zero field validation | Medium | 0 dependents and 10 stars means no public evidence of production use or edge-case hardening |
| Conflict surface | Medium | Any other package or local trait that overrides the same relationship internals may interact unpredictably |
Key questions for the spike
->using(CustomPivot::class), or does it assume the base Pivot class?DB::transaction() boundaries, and is afterCommit behavior defined?sync() of N rows emit N events synchronously? What is the observable overhead?using() sufficient?Stack fit
->using() plus an observer. It is first-party, supported, and gives you created/updated/deleted on the pivot row.BelongsToMany usage and no appetite for touching relationship definitions: the package's trait approach is a legitimate stopgap — but only as vendored code, behind an internal abstraction.Migration path (preferred order)
class Membership extends Pivot, attach via ->using(Membership::class), observe it. Covers ~80% of use cases with zero third-party risk.App\Support\Eloquent\ under our namespace, with our own tests pinned to our Laravel version. Removes the abandoned-dependency risk while preserving behavior.Compatibility checks before any code is merged
composer why-not against the target Laravel version.newPivot() / newExistingPivot() between the package's assumed version and ours.sync with unchanged IDs).BelongsToMany or model event dispatch.Sequencing
using() closes the gap.Maintenance
Support
using() strongly: it fails loudly with framework upgrades, has official documentation, and any Laravel developer can debug it.Scaling
sync() of 5,000 rows produces 5,000 synchronous event dispatches inside the request/transaction. For attachment-heavy batch jobs this is a measurable throughput cost.afterCommit semantics, otherwise a rolled-back transaction leaves downstream consumers having acted on never-committed data.Failure modes (ranked by operational pain)
sync emits detaches and attaches; consumer code often assumes one or the other).Ramp-up
How can I help you explore Laravel packages today?