gigerit/laravel-cascade-delete
gigerit/laravel-cascade-delete brings trait-based cascade deletes to Laravel Eloquent models, automatically removing related records when a parent is deleted. Prevent orphaned rows without fragile DB foreign keys and keep your data consistent and relationships tidy.
Architecture fit. gigerIT/laravel-cascade-delete is a single-purpose Eloquent add-on: it applies a trait (and a service provider / publishable config) to models so that deleting a parent cascades to configured child relations at the application layer. This fills a real gap in Laravel — database-level ON DELETE CASCADE cannot express polymorphic relations, cannot honour SoftDeletes semantics, and is unavailable on SQLite in some setups. For a Laravel codebase that already relies on Eloquent events, the fit is high and non-invasive; it sits alongside your models rather than in the request/HTTP layer, so it is framework-idiomatic rather than a parallel mechanism.
Integration feasibility. Low effort. Composer install, optional config publish, then add the trait and a $cascadeDelete-style relation map to each model. No schema changes, no migrations, no infrastructure. A developer can have a working proof-of-concept on one model in well under a day.
Technical risk. The dominant risk is coverage, not code quality. Application-layer cascades only fire when Eloquent model events fire. Any of the following will bypass the package and leave orphans or, worse, leave a parent deleted with children intact:
Model::where(...)->delete() and other mass/bulk query-builder deletes (no events)DB::table(...)->delete(), raw SQL, and TRUNCATEON DELETE SET NULL / RESTRICT interactions that conflict with the configured cascadeSecondary risks: recursive/nested cascades can be slow and can loop on circular relations if not guarded; deletes are only atomic if the caller wraps them in a transaction; and soft-delete semantics are the subtle part — whether a child is soft-deleted when the parent is soft-deleted, or only force-deleted when the parent is force-deleted, must be verified against actual behaviour rather than assumed.
Key questions.
deleting or deleted, and does it run inside a transaction by default?delete(), on forceDelete(), or both — and can it be configured per relation?SoftDeletes, or is it a pure internal refactor? (Release notes say "Bug Fixes", which implies observable behaviour changed for at least one edge case.)morphMany/morphTo) relations supported, and how are they configured?Assessment of v1.3.4 specifically. This is a patch release containing one bug fix: replacing direct/protected access to soft-delete internals with the public soft-delete API. There are no breaking changes, no deprecations, and no new features. It is semver-safe and is a mild positive maintenance signal — using public API reduces the chance of breakage against future Laravel majors, where soft-delete internals have historically shifted. It does not change the architecture fit, feasibility, or the core risk profile described above; the risk remains coverage and semantics, not this package's internals. This release establishes the baseline assessment rather than revising one.
Stack fit. Requires Laravel with Eloquent and a PHP version consistent with the package's composer.json. Works with MySQL, PostgreSQL, and SQLite; it is especially valuable where FK-level cascades are unavailable or cannot express the relation (polymorphic, soft-deleting). No conflict with laravel/sanctum, spatie/laravel-permission, or other Eloquent-level packages, though any package that itself deletes via the query builder will bypass the cascade.
Migration path. Greenfield: adopt the trait from day one on models with dependent children, and pair it with database FK constraints as defence in depth. Existing application: do not retrofit all models at once. Introduce it per aggregate root, starting with leaf-most, lowest-traffic relations. If FK ON DELETE CASCADE already exists on a relation, choose one mechanism deliberately — running both is redundant and can produce surprising delete counts.
Compatibility. Verify the supported Laravel major against your version before committing; confirm the package boots on your PHP version in CI. Because v1.3.4 moved to the soft-delete public API, it should be more compatible with recent Laravel releases, not less, but confirm the fix targets behaviour you actually depend on. If you have models with custom SoftDeletes overrides, test those explicitly.
Sequencing.
delete(), forceDelete(), and a bulk ->delete() to document the bypass.Maintenance. Small surface area: one composer dependency, one trait, one config file. Upgrade cost is near zero for patch releases like v1.3.4. The real maintenance obligation is internal — keeping the relation map current as the schema evolves. An unmaintained map silently produces orphans. Assign ownership and add a test that fails when a new child relation is added without a cascade decision.
Support. Single-maintainer, small-audience package. Expect limited upstream support and slow responses on edge cases; plan to read the source (it is small) rather than rely on documentation. Mitigate bus-factor risk by pinning a known-good version and keeping the fork option open — the codebase is small enough to vendor or patch in-house if it is abandoned.
Scaling. Cascades execute as N+1 Eloquent deletes, one row at a time, inside the request. Deep or wide graphs (thousands of children, multi-level nesting) will produce slow deletes, long-held row locks, and possible request timeouts. For large aggregates, move deletion to a queued job, wrap it in a transaction, and consider chunking. Also watch replication lag: a large cascade generates substantial binlog volume.
Failure modes.
Ramp-up. Low for developers already fluent in Eloquent events — an hour of reading. The non-obvious knowledge is the bypass list (mass deletes, raw SQL, TRUNCATE) and the soft-delete/force-delete policy, both of which must be written down, not assumed. Budget a short internal write-up plus the feature tests from the sequencing step; that documentation is worth more than the package's own README for preventing incidents.
How can I help you explore Laravel packages today?