Laravel Versionable

repository·5.x·Indexed 20 days ago

https://github.com/overtrue/laravel-versionable

A minimalist package for Laravel that adds version history tracking to Eloquent models. It allows developers to track changes via whitelists or blacklists, revert models to previous states, and view diffs between versions. Supports both DIFF and SNAPSHOT storage strategies, custom version models, and UUID primary keys.

Tokens
2.5K
Snippets
14
Records
15
Agent score
65%

What's inside laravel-versionable

  1. Install Laravel Versionable

    5.x

    Install the package via Composer, publish the configuration and migrations, and then run the migrations to set up the database schema.

    composer require overtrue/laravel-versionable -vvv
    
    php artisan vendor:publish --provider="Overtrue\LaravelVersionable\ServiceProvider"
    
    php artisan migrate
  2. Configure versionable attributes in a Model

    5.x

    To enable versioning, add the Overtrue\LaravelVersionable\Versionable trait to your Eloquent model. You can define which attributes to track using either a whitelist ($versionable) or a blacklist ($dontVersionable).

    Versions are automatically created whenever the model is saved.

    use Overtrue\LaravelVersionable\Versionable;
    
    class Post extends Model
    {
        use Versionable;
    
        /**
         * Versionable attributes (Whitelist)
         * @var array
         */
        protected $versionable = ['title', 'content'];
    
        // Or use a blacklist
        // protected $dontVersionable = ['created_at', 'updated_at'];
    }
  3. Configure version storage strategy

    5.x

    You can change how version data is stored by setting the $versionStrategy property on your model. Supported strategies are:

    • Overtrue\LaravelVersionable\VersionStrategy::DIFF (Default): Only stores the attributes that changed.
    • Overtrue\LaravelVersionable\VersionStrategy::SNAPSHOT: Stores all versionable attribute values in every version.
    protected $versionStrategy = \Overtrue\LaravelVersionable\VersionStrategy::SNAPSHOT;
  4. Publish configuration and migrations

    5.x

    To customize the package behavior or set up the required database schema, you can publish the configuration file and migration files to your application's directories using the Artisan command.

    To publish the configuration file: php artisan vendor:publish --tag=config

    To publish the migrations: php artisan vendor:publish --tag=migrations

    php artisan vendor:publish --tag=config
    php artisan vendor:publish --tag=migrations
  5. Compare differences between two versions

    5.x

    Use the diff() method to compare two versions. This returns an instance of Overtrue\LaravelVersionable\Diff, which provides various output formats (HTML, Text, JSON, etc.) based on the jfcherng/php-diff library.

    $diff = $post->getVersion(1)->diff($post->getVersion(2));
    
    // Get array representation of changes
    $diff->toArray();
    
    // Example output:
    // [
    //    "name" => ["old" => "John", "new" => "Doe"],
    //    "age" => ["old" => 25, "new" => 26],
    // ]
    
    // Other available formats:
    $diff->toText();
    $diff->toJsonText();
    $diff->toHtml();
    $diff->toSideBySideHtml();
  6. Retrieve model versions

    5.x

    The Versionable trait provides several methods to access the history of a model instance:

    • $post->versions: Returns all versions.
    • $post->latestVersion or $post->lastVersion: Returns the most recent version.
    • $post->firstVersion: Returns the first version.
    • $post->versionAt($timestamp): Returns the version from a specific time (accepts string or Carbon instance).
    $post->versions; // all versions
    $post->latestVersion; // latest version
    
    $post->firstVersion; // first version
    
    $post->versionAt('2022-10-06 12:00:00');
  7. Temporarily disable versioning

    5.x

    Use the withoutVersion method to wrap model operations (like create or update) in a closure to prevent version records from being created.

    // Disable during creation
    Post::withoutVersion(function () use (&$post) {
        Post::create(['title' => 'version1', 'content' => 'version1 content']);
    });
    
    // Disable during update
    Post::withoutVersion(function () use ($post) {
        $post->update(['title' => 'updated']);
    });
  8. Use a custom version model

    5.x

    If you want to store versions in a custom table or use a custom model, define a class that extends \Overtrue\LaravelVersionable\Version and assign it to the $versionModel property in your main model.

    // 1. Define custom version model
    class PostVersion extends \Overtrue\LaravelVersionable\Version
    {
    }
    
    // 2. Assign to main model
    class Post extends Model
    {
        use Versionable;
    
        public string $versionModel = PostVersion::class;
    }
  9. Revert a model to a previous version

    5.x

    You can revert a model instance to a specific version using the version ID. You can either persist the change immediately or revert without saving to the database.

    // Revert and save immediately
    $post->getVersion(3)->revert();
    // or
    $post->revertToVersion(3);
    
    // Revert without saving to the database
    $version = $post->versions()->first();
    $post = $version->revertWithoutSaving();
  10. Remove or restore versions

    5.x

    Manage version history by removing specific versions, all versions, or restoring soft-deleted versions.

    // Soft delete
    $post->removeVersion(1);
    $post->removeVersions([1, 2, 3]);
    $post->removeAllVersions();
    
    // Force delete
    $post->forceRemoveVersion(1);
    $post->forceRemoveVersions([1, 2, 3]);
    $post->forceRemoveAllVersions();
    
    // Restore a soft-deleted version
    $post->restoreTrashedVersion($id);
  11. Configure Version UUIDs

    5.x

    The Version model's primary key behavior is controlled by the versionable.uuid configuration key.

    • If versionable.uuid is set to true, the Version model will use string as its key type and automatically generate an orderedUuid for new records during the creating event.
    • If false (default), it uses standard auto-incrementing integer IDs.
  12. Navigate through version history

    5.x

    The Version model provides methods to traverse the timeline of a versionable entity:

    • previousVersion(): Retrieves the version immediately preceding the current one.
    • nextVersion(): Retrieves the version immediately following the current one.
    • previousVersions(): Returns a MorphMany relationship containing all versions created before the current one.
    • isLatest(): Returns true if the current version is the most recent snapshot for the model.
    if ($version->isLatest()) {
        // Do something
    }
    
    $prev = $version->previousVersion();
    $next = $version->nextVersion();