jpnut / eloquent-versioning
An extension for the Eloquent ORM to support 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-05-11 04:00:51 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\Versionable
interface. -
Use the
JPNut\Versioning\VersionableTrait
trait. -
Add the
getVersionableOptions
method to your model. This method must return an instance ofJPNut\Versioning\VersionOptions
. You should define which attributes you would like to version by callingsetVersionableAttributes
and passing an array of attributes:... /** * @return \JPNut\Versioning\VersionOptions */ public function getVersionableOptions(): VersionOptions { return VersionOptions::create() ->setVersionableAttributes(['email', 'city']); } ...
-
Add the
version
column 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_at
timestamp.... 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.