Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Reanimate Laravel Package

mpociot/reanimate

Reanimate adds a recycle bin to Laravel Eloquent models. Use the Reanimate trait to delete records and restore them later without adding soft-delete columns to your tables—deleted models are stored separately, keeping your schema clean while deletions stay undoable.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Reanimate is an additive trait over Laravel's native SoftDeletes — no schema change, no data migration, no service-provider data plane. It slots cleanly beneath our own admin controllers, which is the right place for it: the package owns the data mechanics of bringing a record back, and owns nothing else. It is not an 80% version of a recycle bin. UI, per-role restore permissions, retention windows, bulk semantics, and audit all remain ours. That boundary is the most useful thing this evaluation produces, because it tells us the hard part of an "undo delete" roadmap item is governance and interface, not the database call.

The one genuinely non-trivial capability is the cascade: restoring a parent plus its soft-deleted children across Eloquent relationships. That is the fiddly part and the clearest justification for taking a dependency rather than writing it.

Integration feasibility. High, and cheap. composer require, publish, add the trait to an explicit allowlist of models, call restore inside a guarded controller. Roughly a day to a working spike. No migration on the soft-delete reading.

Technical risk. Four items drive the recommendation:

  1. Mechanism ambiguity — resolve before scoping anything. Sources describe the package both as a thin wrapper over native SoftDeletes and as keeping data available "without relying on soft deletes" (attribute snapshots in configurable storage). These are materially different products. If it truly persists snapshots, that is a second copy of sensitive data with its own retention, encryption, and erasure obligations — a compliance conversation, not an integration task. Read the source first; it is small enough to read end-to-end in minutes.
  2. Security is the real cost, not wiring. The package's entire job is surfacing records we deliberately hid. It has no opinion on authorization, tenant scoping, or whether a record is actually trashed. Ship it behind our policy, our tenant scope, and an explicit trashed check, or we have built an endpoint over our most sensitive data.
  3. Maintenance — ~122 stars, zero dependents, single maintainer, best-effort upstream. An unmaintained dependency on the data-recovery path is a poor trade for code we could write in an afternoon. Mitigation is straightforward: pin, vendor or fork, and treat in-house reimplementation as a scoped afternoon rather than a rewrite.
  4. Cascade semantics are our decision, not a default. "Restoring an order restores its line items" is a product call. Ordering, FK constraints, polymorphic relations, deep cascades, UUID/ULID keys, and multi-tenancy all need verification against our real schema. Without a transaction, a partial cascade leaves state no one designed.

Key questions.

  • Which mechanism is real — native soft-delete wrapper, or snapshot storage? (Gates everything downstream.)
  • What are the illuminate/* and PHP constraints, and when was the last commit or release?
  • Does it register routes at all, and would they sit behind our middleware and survive route:cache?
  • Does the cascade follow our relationship definitions, and in what order? How does it handle a child that was hard-deleted or independently restored?
  • Does it reliably fire restored events we can hook for audit and downstream repair?
  • What happens on a unique-constraint collision when a natural key (slug, email) was reused after deletion?

Integration Approach

Stack fit. Laravel application already using SoftDeletes consistently. If soft deletes are sporadic across the schema, recovery becomes a per-entity special case rather than a coherent capability — deprioritize and fix the data model first. This package adds nothing on top of hard deletes and cannot recover what no longer exists.

Migration path. None required. Adoption is an allowlist decision, not a data migration: add the trait only to models where we have decided "delete is reversible here." Never on a shared base model — an allowlist is the whole point.

Compatibility. Confirm version constraints and release recency before committing. If the package predates our Laravel version, fork it (~50 lines) rather than installing under --ignore-platform-reqs. Verify route registration and route caching if applicable. Verify withTrashed() route model binding — binding silently 404s on trashed records otherwise, which is the most common "the package is broken" moment.

Sequencing.

  1. Source read to resolve the mechanism ambiguity and confirm trait namespace.
  2. Version and maintenance check.
  3. Install; trait on exactly one model.
  4. One guarded admin controller action: auth + can:restore,invoice policy + explicit tenant scope + abort_unless($invoice->trashed(), 409), wrapped in DB::transaction(). Do not expose package routes directly.
  5. Register an eloquent.restored: * listener for audit (actor, class, key, timestamp, request ID) and to repair everything that already treated the delete as final — search index, cache, denormalized counters, outbound webhooks.
  6. Mirror the cascade on delete. Asymmetric cascade logic is how "delete means X except when it means Y" enters a codebase.
  7. CI: one feature test per releasable model — create → delete → restore → assert deleted_at null, children restored, audit row present.
  8. Only then consider bulk restore: loop per record, collect per-record outcomes, return a partial-failure payload. All-or-nothing bulk restore reverts 200 good restores when one record collides.
  9. Decide keep / fork / reimplement before this sits on the critical recovery path.

Operational Impact

Maintenance. We own it from day one. Pin the version, vendor or fork the source, and set an explicit fork trigger (upstream dormancy, a Laravel major bump). Ongoing overhead is small but non-zero; the offset is that replacement cost is bounded and well understood, which keeps lock-in low.

Support. The measurable win is deflection of accidental-deletion tickets — count deletion-related tickets before and after and use the delta to justify or retire the feature. Support burden then shifts to governance: who is permitted to restore, what is restorable, and can we answer "who brought this back?" A restore is a production mutation and needs an audit trail the first time someone asks.

Scaling. Restore is a low-volume, admin-only, single-row-plus-cascade write — throughput is not the concern. The concerns are cascade depth (N children, deep graphs, polymorphic hops) and bulk operations (per-record outcomes, unique collisions, partial failure). Note that restore() bumps updated_at, so anything keyed to "last modified" now reports the record as changed today, which may be wrong for reporting.

Failure modes.

  • Partial cascade outside a transaction → orphaned or partially restored data.
  • restore() on a non-trashed model returns true and does nothing — silently idempotent; guard with a 409 if the API should be honest.
  • Unique constraint on a reused natural key → QueryException; decide up front to block, suffix, or fail loudly.
  • A restoring observer returning false aborts the restore — useful as a policy hook, a footgun when unrelated.
  • Scheduled retention purges holding queued payloads that still reference a now-restored row.
  • Children independently restored or hard-deleted in the interim; deep cascades and multi-tenant scopes not exercised by the README.

Ramp-up. Low. The API surface is one trait and one call; an engineer integrates in a day. The actual learning — and where the estimate should sit — is the authorization model, per-relationship cascade semantics, and audit, not the package.

Recommendation. Adopt as a time-boxed spike or internal admin tool and as a validated reference, not as a permanent dependency on the sensitive-data recovery path. It buys a day and a clean answer to "is undo-delete worth building?" If the feature graduates, fork it or reimplement behind our own controller and policies and retire the dependency.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource