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

Memento Laravel Package

esplora/memento

Memento is a Laravel package for versioning Eloquent models. It captures snapshots of model state, helping you track changes and restore previous versions, adding simple audit history and model revision support to your application.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Version 3.0.0 is a compatibility major, not a feature release. Per the changelog it adds Laravel 10, PHP 8.2 and PHPUnit 10 support. The major bump implies 2.0.0's floor (older Laravel / PHP 8.0–8.1) is no longer supported — pin ^3.0 only if you're on Laravel 10 + PHP 8.2; otherwise stay on ^2.0 for now.
  • Install with composer require esplora/memento and run the package migrations before touching any model. Snapshot data lives in its own table, so the migration is not optional.
  • Look first at: the published config file (what gets recorded, retention), the migration (column types and indexes — this tells you how much a snapshot actually costs), and the trait/interface you add to a model.
  • First use case: pick one model where "what did this look like last Tuesday?" is a real business question — an order, a price list, a CMS page. Add the package's trait to that model, save a few records, and inspect the snapshot rows before wiring it into anything else. Do not start by adding it to every model.

Implementation Patterns

  • Apply the trait selectively. Memento-style packages are opt-in per model; treat that as a design constraint, not a limitation. High-value, low-write-volume models (orders, invoices, published content, pricing rules) are ideal. Models with high write churn (sessions, counters, sync jobs) will bury you in rows.
  • Snapshot on meaningful transitions, not every save(). If the package hooks into the updated event by default, use an escape hatch (saveQuietly(), a guard attribute, or a custom event list) so noisy fields like last_seen_at or counters don't generate snapshots.
  • Treat restore as a write operation, not a time machine. Restoring a snapshot rewrites the model's attributes; it typically will not re-run domain side effects (stock decrements, emails, search index updates). Wrap restores in DB::transaction() and follow with whatever your app normally does on a state change — fire your own event, reindex, notify.
  • Capture attribution explicitly. Most implementations auto-record the authenticated user. In queued jobs, console commands and scheduled tasks auth()->user() is null, so snapshots end up unattributed. Pass the actor through (e.g. Auth::login() in the job, or a package-supported actor override) if provenance matters.
  • Pair with an observer for context. When you snapshot an order, the useful question is usually "why did it change?" Add the reason (admin action, import, API call) into the surrounding code path so the snapshot row carries meaning beyond raw attributes.
  • Testing pattern: use factories, mutate, assert the snapshot count and the diff — not the whole serialized payload. In Laravel 10 / PHPUnit 10, convert @test / docblock annotations to attributes (#[Test]) and setUp(): void signatures if you're porting an app test suite alongside the upgrade.
  • Schedule pruning from day one. Add a model/command to the scheduler in the same PR that introduces the package. Retention is easier to configure before the table is 2 million rows deep.
  • Upgrade path for the major: bump composer.json constraints, run the full suite, and specifically re-test anything that touches snapshot serialization — model $casts, date formats and Carbon versions are the usual sources of silent drift between Laravel majors.

Gotchas and Tips

  • The breaking change is the support matrix. If you're mid-upgrade to Laravel 10 and still on PHP 8.1, you cannot take 3.0.0. Check composer why-not esplora/memento 3.0.0 before assuming a dependency conflict is the package's fault.
  • Table growth is the #1 operational pitfall. Snapshots store serialized attributes; wide models with long text or JSON columns produce large rows fast. Verify the migration indexes the morph columns and created_at, and prune aggressively.
  • Serialization surprises. Casts, $hidden, $appends and custom accessors determine what lands in the payload. Change a cast later and old snapshots still hold the old representation — restoring an old snapshot can therefore write a value your current cast doesn't handle. Test restore paths after any cast/attribute change.
  • Restores bypass your model events in most implementations. Anything downstream of updated (audit logs, webhooks, cache busting, Scout indexing) will not fire. Do it manually.
  • Deletes and relations. Confirm whether snapshots survive model deletion and whether related models are captured. If you need "restore a deleted order with its lines", you likely need to snapshot the relation separately or store the parent id in your own table.
  • Queue and multi-tenant context. Actor resolution and tenant scoping both rely on request-time state that doesn't exist in workers. Assert on this in tests with Bus::fake()-style jobs or an actual queued run before shipping.
  • Debugging tip: when snapshots look empty or wrong, check the model's $fillable/$guarded and whether the write went through saveQuietly() or a raw query builder update — bypassing Eloquent bypasses the package entirely.
  • Extension points to look for (and confirm against the README for 3.0.0): a custom snapshot model binding via the container, a config-driven list of tracked attributes, morph map integration, and a disable switch for seeders/imports. Wrap seeders and bulk imports with the disable switch or you'll snapshot your entire fixture set.
  • Pin the version explicitly in composer.json ("esplora/memento": "^3.0") and read the full changelog diff between 2.0.0 and 3.0.0 before deploying — the release notes here are terse, so the actual diff is where any behavioural changes would hide.
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.
alphabalex/messaging-made-easy
rawphp/warp
shootkiran/merobug
narakode/fineauth
numencode/wn-syncops-plugin
ibnnajjaar/mib-global-pay
ably/pubsub-server
mstfkhazaal/defender
mfonte/base62x
karnoweb/metapilot
tobya/bcsapiwrapper
swalker2/cpanel
vish4395/laravel-translation-manager
morningtrain/economic
teksite/systeminfo-laravel
atomcms/voting
run6/weather
siokas/laravelembeddirectives
adamlien/pkuuids
gilsonsouza/lara-doc-generator