evence/soft-deleteable-extension-bundle
Symfony bundle that extends Gedmo's SoftDeleteable listener, adding onSoftDelete annotations to entity associations. Supports CASCADE, SET NULL, and SUCCESSOR behaviors so references are handled cleanly when a parent is soft-deleted, avoiding Doctrine errors.
Feature scoping for delete, restore, and retention flows. If the roadmap includes user-facing delete/restore, GDPR-style retention windows, audit history, or archival, this package makes soft-delete behavior correct rather than merely present. Today, soft-deleting a parent leaves child records pointing at rows that no longer appear active — producing Doctrine EntityNotFoundException-class errors, broken joins, and inconsistent reporting. Each customer-facing "delete" feature becomes cheaper to ship and safer to operate.
Build vs. buy (really: adopt, fork, or reimplement). The package resolves a gap open in Gedmo/DoctrineExtensions since 2012 in roughly one composer require plus a per-relationship annotation. The buy side is trivially cheap (MIT, tiny surface), which shifts the real decision to adopt-and-own vs. fork vs. build in-house. With ~57 stars and zero dependents, it is not a dependency you lean on — it is a spec you inherit. That is still valuable: the three behaviors are already named, coded, and documented, so an internal reimplementation is a 1–3 day task rather than an open design question.
Cascade semantics become an explicit product decision, not an implementation accident. The three modes map one-to-one onto behaviors the product must specify anyway:
CASCADE → "archiving a seller archives their listings; they disappear from the storefront."SET NULL → "unlinking is not deleting" — the child record survives as an orphan and must remain queryable/supportable.SUCCESSOR → "this record now belongs to its replacement" — reassigning references during account merges, plan migrations, or brand consolidation.
Choosing per relationship is a data-policy call (retention, compliance, reporting integrity), and this package lets that decision live in reviewable code instead of ad hoc service logic or one-off migration scripts.Roadmap de-risking for migrations and entity consolidation. SUCCESSOR is the standout capability. Account merges, tenant consolidation, plan/ownership transitions, and catalog brand migrations are usually hand-written scripts that are risky and hard to reverse. Packaging that behavior as a declarative mapping meaningfully de-risks those initiatives.
Stack-commitment signal — and a correction to the evaluation framing. Despite being listed as a "Laravel/PHP package," this is a Symfony bundle built on Gedmo's Doctrine SoftDeleteable listener for Doctrine ORM. There is no Eloquent integration, service provider, or Laravel manifest. So the decision it informs is "are we, or are we remaining, a Symfony + Doctrine + Gedmo shop?" — not "which Laravel package shall we use?" On Laravel/Eloquent, model events already cover cascade/set-null/successor, and this package is simply inapplicable. If a team is considering introducing Doctrine solely to gain this behavior, that is a no.
Concrete use cases worth scoping: marketplace listings tied to sellers, multi-tenant records attached to a soft-deleted parent, catalog items attached to a discontinued brand, CRM records attached to a merged account, subscription artifacts attached to a churned organization.
Consider it when all of the following hold:
SUCCESSOR in particular has no clean built-in equivalent.Look elsewhere when:
deleting/deleted model events, or an explicit service enforcing cascade semantics.ON DELETE constraints with hard deletes, or by a dedicated archival / event-sourced design. Soft delete is often the wrong default — do not adopt this to paper over an unresolved retention model.For executives: This is a small, free (MIT) library that closes a long-standing gap in our data layer. Today, when we "soft delete" a record, related records are left pointing at something that no longer appears active — which surfaces to users as errors and to the business as inconsistent reporting. The library lets us declare, per relationship, whether dependent records should be archived too, detached and preserved, or handed over to a successor record. That converts an implicit data-policy decision into explicit, reviewable code and makes every future "delete/restore" feature cheaper and safer to ship. There is no data migration and no new infrastructure — the work is a package install plus a mapping annotation per relationship, tested one relation at a time. The cost is negligible; the risk is that this is a low-profile, single-maintainer package with near-zero adoption. Recommendation: pilot it in one non-critical module, vendor the code internally, and pin the version rather than treating it as an external dependency we rely on blindly. If the pilot reveals compatibility friction, the fallback is a ~1–3 day internal implementation — and we still come out ahead, because this package has already specified the semantics for us.
For engineering: It is a Symfony bundle extending Gedmo's SoftDeleteable listener, adding an onSoftDelete mapping with CASCADE, SET NULL, and SUCCESSOR modes — the ORM-layer equivalent of SQL ON DELETE semantics, applied at soft-delete time. Integration is composer require with a pinned version, bundle registration, and annotating the owning side of associations. No DDL, no backfill, no deployment choreography. Before adopting, resolve five things: (1) supported PHP / Doctrine ORM / DBAL / Gedmo matrix and whether CI exists; (2) attribute-mapping support — the README shows annotations, which is a dead end on ORM 3; (3) whether cascades run in a single transaction or can partially commit; (4) cycle/recursion protection for CASCADE and SUCCESSOR; (5) coverage of bulk DQL DELETE and programmatic remove() paths, and which association types (ManyToOne only, or OneToOne/ManyToMany too). Treat the dependency as fork-first: vendor the source or hold a private fork with our own CI matrix, which converts an availability risk into a known, low-cost maintenance line and lets us patch Doctrine/Gedmo compatibility ourselves. If any gate fails, implement the same three behaviors as an internal listener — a reasonable outcome, since the package's durable value is the specification, not the code.
How can I help you explore Laravel packages today?