Weave Code
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

Laravel Rewind Laravel Package

avocet-shores/laravel-rewind

Full version control for Eloquent models: rewind, fast-forward, restore, diff, and query point-in-time state. Uses a hybrid engine (diffs + snapshots) with configurable intervals, thread-safe locking, batch revisions, queued writes, and pruning.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require avocet-shores/laravel-rewind
    php artisan vendor:publish --provider="AvocetShores\LaravelRewind\LaravelRewindServiceProvider"
    php artisan migrate
    
  2. Enable Versioning: Add the Rewindable trait to your Eloquent model:

    use AvocetShores\LaravelRewind\Traits\Rewindable;
    
    class Post extends Model
    {
        use Rewindable;
    }
    
  3. Add Version Column: Run the migration to add the current_version column:

    php artisan rewind:add-version
    php artisan migrate
    

First Use Case

Track Changes and Rewind:

$post = Post::find(1);
$post->update(['title' => 'Updated Title']);

// Rewind to previous state
Rewind::rewind($post); // Back to 'Old Title'

// Fast-forward to latest
Rewind::fastForward($post); // Back to 'Updated Title'

Implementation Patterns

Core Workflows

  1. Version Navigation:

    // Jump to a specific version
    Rewind::goTo($post, 3);
    
    // Get attributes at a specific version
    $attributes = Rewind::versionAt($post, Carbon::parse('2025-01-15'));
    
  2. State Restoration:

    // Preview without audit trail
    Rewind::goTo($post, 2);
    
    // Create a new version from an old state (audit trail preserved)
    Rewind::restore($post, 2);
    
  3. Change Inspection:

    // Diff between versions
    $diff = Rewind::diff($post, 1, 3);
    
    // Replay history
    Rewind::replay($post, 1, 5, function ($version, $attributes) {
        // Process each version
    });
    

Integration Tips

  • State Transitions: Track critical fields (e.g., status) separately:

    class Order extends Model
    {
        use Rewindable;
        protected array $rewindStateFields = ['status', 'payment_status'];
    }
    

    Query transitions:

    $order->versions()->whereStateBecame('status', 'shipped')->get();
    
  • Batch Versioning: Group related changes (e.g., order + items):

    $batchUuid = Rewind::batch(function () {
        $order->update(['status' => 'shipped']);
        $item->update(['shipped_at' => now()]);
    });
    
  • Exclude Sensitive Data:

    public static function excludedFromVersioning(): array
    {
        return ['password', 'api_token'];
    }
    
  • Metadata Attachment:

    Rewind::withMeta(['reason' => 'Bulk update', 'ticket' => 'JIRA-123']);
    $post->update(['title' => 'New Title']);
    

Queued Versioning

For high-traffic models, enable queued version creation:

// config/rewind.php
'listener_should_queue' => true,

Gotchas and Tips

Pitfalls

  1. Lock Timeouts: Concurrent writes may fail if cache locks time out. Configure handling in config/rewind.php:

    'on_lock_timeout' => 'event', // Options: 'log', 'event', 'throw'
    
  2. Snapshot Interval: Higher values (e.g., snapshot_interval: 20) save storage but slow down reconstruction. Default is 10.

  3. Amend vs. Exclude: Use amendCurrentVersion() for non-versioned changes (e.g., counters). Use excludedFromVersioning() for permanently hidden fields.

  4. Pruning Side Effects: Pruning converts the new oldest version into a snapshot. Test with --pretend first:

    php artisan rewind:prune --keep=50 --pretend
    

Debugging

  • Version Reconstruction: If Rewind::getVersionAttributes() returns incomplete data, check the snapshot_interval or manually trigger a snapshot:

    Rewind::forceSnapshot($post);
    
  • Batch Queries: Ensure batch_uuid is included in queries for grouped versions:

    RewindVersion::inBatch($batchUuid)->get();
    
  • State Transitions: If transitions are missing, verify $rewindStateFields is correctly defined.

Extension Points

  1. Custom Version Model: Extend RewindVersion for additional fields:

    // config/rewind.php
    'version_model' => App\Models\CustomRewindVersion::class,
    
  2. Event Listeners: Listen for version events (e.g., RewindVersionCreated):

    event(new RewindVersionCreated($version));
    
  3. Pruning Logic: Override default pruning behavior by extending the PruneVersions command.

Performance Tips

  • Snapshot Optimization: Increase snapshot_interval for read-heavy workloads (e.g., 20).
  • Queued Processing: Enable 'listener_should_queue' => true for write-heavy models.
  • Indexing: Add indexes to rewind_versions for large datasets:
    Schema::table('rewind_versions', function (Blueprint $table) {
        $table->index('model_type');
        $table->index('model_id');
        $table->index(['model_type', 'model_id', 'version']);
    });
    

Common Anti-Patterns

  • Overusing amendCurrentVersion: Avoid for critical changes; use restore() instead to preserve audit trails.
  • Ignoring Pruning: Regularly run rewind:prune to avoid storage bloat.
  • Mixed State Fields: Avoid mixing state fields (e.g., status) with non-state fields in $rewindStateFields.
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai