dyrynda/laravel-cascade-soft-deletes
Adds cascading soft deletes to Laravel Eloquent models via a simple trait. Soft-deleting a parent also soft-deletes its related children, and restoring the parent restores them, filling the gap left by Laravel's built-in cascade, which only handles hard deletes.
Architecture fit
CascadesSoftDeletes, plus a restore counterpart in recent versions) that attaches to Eloquent models via a $cascadeSoftDeletes relationship array. No service provider, no config file, no migrations, no schema changes — it operates purely on model lifecycle events.deleting model event and are executed as query-builder mass updates executed in chunks on the relation, not as per-model deletes. That means child model events (observers, audit listeners, search-index sync, broadcast/queue hooks) do not fire.UPDATE and can exhaust memory or lock a large row set in a single statement — was addressed upstream. 4.6.1 carries fix: iterate chunk collection individually in cascading deletes, which confirms chunked iteration is present in the 4.6.x line. This is a meaningful improvement in the package's architectural profile: cascades are now memory-bounded and issued as a series of smaller statements.Integration feasibility
composer require dyrynda/laravel-cascade-soft-deletes, add the trait, declare the relationship list. Estimated effort per model is minutes, not days.SoftDeletes; it is a behavior change, not a feature addition, so it needs deliberate sign-off rather than an opportunistic PR.$cascadeSoftDeletes contract, and the cascade semantics are unchanged. It is safe to adopt at 4.6.1 as the floor, and any model already on an earlier 4.x should be bumped to 4.6.1 specifically to pick up the chunk-iteration correctness fix.Technical risk
forceDelete() bypasses the cascade by design. If database-level ON DELETE CASCADE foreign keys also exist, deletion behavior becomes ambiguous and can surface as constraint errors.^4.4.2 bump is dev-only. It does not enter our runtime dependency graph and imposes no constraint on our application. Do not let a composer.lock diff on dev tooling trigger a false breaking-change review.Key questions
ON DELETE CASCADE or restrictive foreign keys that would interact with force deletes?Stack fit
SoftDeletes, no global scopes introduced, no query interception. Composes with policy/authorization layers, API resources, and existing repository patterns.Migration path
parent.deleted_at IS NOT NULL AND child.deleted_at IS NULL) and decide whether to soft-delete or intentionally retain them.Compatibility
composer.json Laravel and PHP constraints against our pinned framework version before committing; the package tracks framework releases but not always the newest major immediately.deleting listeners from other packages (activity logging, model status/history packages, media libraries). Multiple listeners on the same event are ordered by registration and can produce surprising interaction.boot()/booted() logic.Sequencing
$cascadeSoftDeletes arrays leaf-first, so children are already cascade-capable when parents are enabled.Maintenance
$cascadeSoftDeletes arrays: they are declarative configuration that silently rots when relationships are renamed or added. Renaming a relationship without updating the array produces a runtime error on delete — better than silence, but only caught if deletion paths are tested.composer.json and treat major bumps as reviewable changes. Patch bumps can be accepted routinely, but this release is a reminder that a patch can carry a behavioural fix — read patch notes for this package rather than fast-forwarding blindly.Support
Scaling
UPDATE; they now execute across chunked statements, so per-statement row-lock scope and memory pressure are bounded. Wide fan-out is no longer a "one giant UPDATE holds locks for the whole cascade" failure mode.Failure modes
Ramp-up
How can I help you explore Laravel packages today?