romanzipp/laravel-previously-deleted
Laravel package for handling previously deleted Eloquent models. It helps you detect records that were soft-deleted in the past and use that information when validating, restoring, or creating new entries, helping avoid duplicate or conflicting data.
Architecture fit. Unchanged by 1.1.0. This is a single-trait, event-driven add-on: it hooks the Eloquent deleted model event and serializes getAttributes() into a polymorphic previously_deleted table (model type, model key, JSON payload). Integration surface is one use statement per model plus a published migration — near-zero coupling, no service provider gymnastics, trivially removable. It fits only architectures where deletes are hard deletes issued through Eloquent. It remains conceptually redundant with SoftDeletes (do not run both on the same model) and with any existing audit log (owen-it/laravel-auditing, spatie/laravel-activitylog) or event-sourced store.
Integration feasibility. composer require, vendor:publish, migrate, add trait. Half a day to a working spike on one model. 1.1.0 does not change the effort estimate; it only moves the ceiling of what runs unmodified from Laravel 6 to Laravel 7. The blocker is still the version matrix, not the integration work.
Technical risk, ranked:
composer.json once; it does not tell us there is a maintainer reviewing issues, cutting security fixes, or planning for Laravel 8+. Treat this as code you are adopting, not a dependency you are consuming. The project remains 3 stars, 0 dependents, with no evidence of sustained activity.illuminate/* constraints will still not admit a modern stack unmodified, and PHP 8.x will still surface dynamic-property deprecations and overridden-method return-type errors. Expect a fork-and-patch before it runs on anything we operate. Verify before assuming: confirm whether 1.1.0 declares ^6.0|^7.0 or ^7.0 only — if the latter, this release silently dropped Laravel 6 and is a constraint-level breaking change for any team still on 6.Model::where(...)->delete()) or DB-level ON DELETE CASCADE. Cascade-deleted child rows are silently lost — frequently the exact data you wanted to recover. 1.1.0 does not address this, and given the release's scope, is unlikely to.getAttributes() captures column values only: no relations, no files/media, no cast round-trip guarantees. "Restore" is a re-insert, not an undo — unique constraints, FK targets, and IDs will collide.Key questions before committing:
Stack fit. Laravel + Eloquent, MySQL/Postgres with JSON columns. No external services, no queues, no runtime calls — an unusually low-blast-radius dependency. Unchanged.
Migration path. Vendor the package (composer VCS repository entry or copy into app/Support), pin to a fork we control, relax composer.json constraints, fix PHP 8 breakages, then publish the migration. Do not depend on Packagist upstream for anything production-critical. 1.1.0 does not shorten this path — it removes one of roughly five major-version gaps.
Compatibility. Validate against our exact Laravel minor; the package's declared ceiling is now 7, so anything we run is a patch target, not a supported configuration. Test JSON column behavior per engine (MySQL JSON vs. Postgres jsonb); check payload size against max_allowed_packet or TOAST limits for wide models. Re-read the 1.1.0 diff before forking: it is small enough to audit in minutes, and auditing it is the cheapest way to confirm nothing beyond constraints changed.
Sequencing.
(model_type, model_id) and created_at, admin-only read path.Maintenance. No upstream support commitment demonstrated. 1.1.0 is a single-purpose release, not the start of a maintenance cadence, and we should not plan around a 1.2.0. This needs a named owner and a standing review at every Laravel upgrade. That cost is permanent and remains the single largest line item; 1.1.0 does not reduce it.
Support. No community, no issue triage, no security advisories. Any defect in the pattern becomes ours. A Laravel 7 bump does not create a support channel.
Scaling. Storage grows linearly and monotonically with delete volume. A table churning 10k deletes/day at 2KB payloads is ~7GB/year. Plan retention windows, partitioning, or archival; alert on table size. Read load is negligible (recovery is rare) — the risk is unbounded disk and index bloat, not query throughput.
Failure modes.
Ramp-up. Low for engineers — one trait, one table, roughly an hour to understand. The real ramp is organizational: teaching teams to route deletes through Eloquent, to use the recovery path during incidents, and to know when not to trust it. Unaffected by 1.1.0.
Recommendation for the record. 1.1.0 changes the assessment's facts but not its conclusion. Laravel 7 support moves the package from "five majors behind" to "four majors behind," on a framework that itself went end-of-life in 2021, delivered as a constraint bump with no accompanying maintenance signal. The idea is sound and the implementation is small, but 3 stars, zero dependents, and a single-line release after a long quiet period still make this a poor direct dependency despite the MIT license. Use it as a reference implementation for a comparable in-house build; adopt the fork only if the spike proves the event-coverage gaps are acceptable for our actual delete patterns.
How can I help you explore Laravel packages today?