jpnut / eloquent-versioning
An extension for the Eloquent ORM to support versioning.
Installs: 7
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 29
Open Issues: 0
pkg:composer/jpnut/eloquent-versioning
Requires
- php: ^7.4
- laravel/framework: ^6.0
Requires (Dev)
- orchestra/testbench: ^4.0
- phpunit/phpunit: ^8.5
This package is auto-updated.
Last update: 2025-10-11 04:47:02 UTC
README
This package provides a trait that adds versions to an Eloquent model (forked from proai/eloquent-versioning).
New versions are created whenever a model is updated. Versions are stored in a separate table for each model (e.g. user_versions).
The package allows for a mixture of versioned and non-versioned attributes.
By default, queries are scoped to merge records in the parent table with the latest version. Additional scopes exist to merge records at a particular version or point in time.
Installation
This package can be installed through Composer.
composer require jpnut/eloquent-versioning
Usage
To add versions to your model you must:
-
Implement the
JPNut\Versioning\Versionableinterface. -
Use the
JPNut\Versioning\VersionableTraittrait. -
Add the
getVersionableOptionsmethod to your model. This method must return an instance ofJPNut\Versioning\VersionOptions. You should define which attributes you would like to version by callingsetVersionableAttributesand passing an array of attributes:... /** * @return \JPNut\Versioning\VersionOptions */ public function getVersionableOptions(): VersionOptions { return VersionOptions::create() ->setVersionableAttributes(['email', 'city']); } ...
-
Add the
versioncolumn to the table of the model which you wish to version. This keeps track of the current version.... Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->integer('version')->unsigned()->nullable(); $table->string('name'); $table->timestamps(); $table->softDeletes(); }); ...
-
Create a table to contain the versions. This table should contain a reference to the parent model (
parent_id), the version numberversion, all versionable attributes (email,city), and thecreated_attimestamp.... Schema::create('user_versions', function (Blueprint $table) { $table->integer('parent_id')->unsigned(); $table->integer('version')->unsigned(); $table->string('email'); $table->string('city'); $table->timestamp('created_at'); $table->primary(['parent_id', 'version']); }); ...
It is assumed that the version table name takes the form {entity}_versions where entity is the singular form of the entity noun (e.g. users and user_versions). It is possible to override this and all column names by calling the relevant method on the options object (the following shows the default settings).
... /** * @return \JPNut\Versioning\VersionOptions */ public function getVersionableOptions(): VersionOptions { return VersionOptions::create() ->saveVersionKeyTo('version') ->useVersionTable('user_versions') ->saveVersionTableKeyTo('version') ->versionTableForeignKeyName('parent_id') ->versionTableCreatedAtName('created_at'); } ...
Example
use Illuminate\Database\Eloquent\Model; use JPNut\Versioning\Versionable; use JPNut\Versioning\VersionableTrait; use JPNut\Versioning\VersionOptions; class YourEloquentModel extends Model implements Versionable { use VersionableTrait; /** * @return VersionOptions */ public function getVersionableOptions(): VersionOptions { return VersionOptions::create() ->setVersionableAttributes(['email', 'city']); } ... }
You can retrieve the model at a specific version by using the atVersion scope
Model::atVersion(1)->find(1);
You can retrieve the model at a specific point in time by using the atTime scope
Model::atTime(now()->subDay())->find(1);
Note that this will attempt to find the last version created before the time supplied. If there are no such versions, the method will return null.
You can disable the global scope by using the withoutVersion scope
Model::withoutVersion()->find(1);
You can obtain all versions in the form of a relationship by calling the versions property (or method) on a model instance
$model->versions;
Note that by default a generic Version model is used. You can change this model by overwriting the versions method and returning your own HasMany relationship.
You can revert to a previous version by calling the changeVersion() method with the desired version as an argument.
$model->changeVersion(1);
Note that this creates a new version with the same versionable attribute values as the version specified (rather than changing the value of the version column in the parent table).
Tests
The package contains some integration tests, set up with Orchestra. The tests can be run via phpunit.
vendor/bin/phpunit
Contributing
Create a Pull Request!
Alternatives
- mpociot/versionable
- overtrue/laravel-versionable
- proai/eloquent-versioning
- venturecraft/revisionable
License
The MIT License (MIT). Please see License File for more information.