laragear/rewind
Rewind adds undo history to Laravel Eloquent models. It records model changes and lets you restore previous states, so you can safely revert updates, deletes, and other modifications through a simple API—ideal for audit trails, recovery, and user-facing undo features.
Rewind adds a "time machine" for Eloquent models: it persists a snapshot of a model's attributes on every create/update/delete and lets you restore a record to a previous snapshot or point in time. That makes it a natural fit for admin dashboards, CMS editing flows, and any app where "undo my last change" is a real product requirement.
Minimal setup for v3.0.0:
composer require laragear/rewind, then publish the migration and (optionally) the config:
php artisan vendor:publish --tag=rewind-migrationsphp artisan vendor:publish --tag=rewind-configphp artisan migrateconfig/rewind.php and the generated rewinds migration are the two files that tell you how v3 behaves — read them before touching application models. v3.0.0 is a major version bump from v2.0.0, so if you are upgrading, diff the published files against your existing copies rather than overwriting blindly.use Laragear\Rewind\Rewindable;
class Post extends Model
{
use Rewindable;
}
$post = Post::create(['title' => 'Draft']);
$post->update(['title' => 'Final']);
$post->rewind(); // restores the previous snapshot
Because v3.0.0's changelog is only a compare link, verify the exact trait namespace, config keys, and available rewind methods against the README/UPGRADING docs for this tag before relying on any single method name — those are the most likely surfaces to have moved between v2 and v3.
Per-model trait tracking. The trait is the whole integration surface. Any model that needs history gets it; models that don't stay untouched. This is the cleanest way to keep the rewinds table scoped to records that actually matter.
Rewinding to a snapshot vs. a date. Day-to-day you'll typically use three shapes:
$model->rewind() for the common "undo the last save" case in an editor.Treat the exact method names as v3-specific and confirm them in the docs before building UI on top.
Admin/audit dashboards. Because each rewind record carries the full attribute payload, you can render a diff view ("what changed, when, by whom" — the actor is whatever you enrich your snapshot with) and give operators a one-click restore. Pair this with a normal audit log if you need immutable compliance records; rewinds are mutable history by design.
Bulk / operational rewinds. Rewinding is a write operation that should be deliberate. Wrap multi-model operations in a DB transaction so a partial failure doesn't leave related records in mismatched states.
Suppress tracking where it's noise. Seeders, factories, imports, and one-off data migrations will flood the table. Scope tracking off around those code paths (the trait exposes a without…-style escape hatch in v2/v3 — check the current name in the docs). This is the single most important pattern to bake into your base test case and seeders.
Retention scheduling. History grows monotonically. Add a scheduled prune (or your own where('created_at', '<', ...)->delete()) to the app's scheduler as part of rollout, not as an afterthought.
Composing with other Laragear packages. If you already use packages like Login Link, Gag, or Pwned Passwords, keep each package's config and publish tags separate; don't assume shared conventions across the family.
v2.0.0...v3.0.0 is your only changelog. Before upgrading production: publish the new migration into a scratch branch and diff it, re-read the config, and run the full test suite. Expect at minimum a new migration and possibly renamed config keys/methods.Post::where(...)->update(...)), raw SQL, and insert bypass Eloquent model events, so they leave no rewind. Anything you need reversible must go through model instances.updated events, and downstream side effects run. Guard against infinite loops (an observer that writes → history → observer…) and against re-firing notifications on restore.php artisan config:clear — stale cached config is the usual reason tracking silently "stops working" after a deploy.app.timezone and DB timezone agree, and be explicit about the comparison boundary (inclusive/exclusive).rewinds table populated → model change went through Eloquent (not a bulk query) → tracking not suppressed in that scope → config cache cleared.composer update clean for the next major.(rewindable_type, rewindable_id, created_at) early; a raw history table will scan painfully at scale.How can I help you explore Laravel packages today?