It's a minimalist way to make your model support version history, and it's very simple to revert to the specified version.
- PHP >= 8.1.0
- laravel/framework >= 9.0
- Keep the specified number of versions.
- Whitelist and blacklist for versionable attributes.
- Easily revert to the specified version.
- Record only changed attributes.
- Easy to customize.
composer require overtrue/laravel-versionable -vvv
First, publish the config file and migrations:
php artisan vendor:publish --provider="Overtrue\LaravelVersionable\ServiceProvider"
Then run this command to create a database migration:
php artisan migrate
Add Overtrue\LaravelVersionable\Versionable
trait to the model and set versionable attributes:
use Overtrue\LaravelVersionable\Versionable;
class Post extends Model
{
use Versionable;
/**
* Versionable attributes
*
* @var array
*/
protected $versionable = ['title', 'content'];
// Or use a blacklist
//protected $dontVersionable = ['created_at', 'updated_at'];
<...>
}
Versions will be created on the vensionable model saved.
$post = Post::create(['title' => 'version1', 'content' => 'version1 content']);
$post->update(['title' => 'version2']);
$post->versions; // all versions
$post->latestVersion; // latest version
// or
$post->lastVersion;
$post->versions->first(); // first version
// or
$post->firstVersion;
$post->versionAt('2022-10-06 12:00:00'); // get version from a specific time
// or
$post->versionAt(\Carbon\Carbon::create(2022, 10, 6, 12));
Revert a model instance to the specified version:
$post->getVersion(3)->revert();
// or
$post->revertToVersion(3);
$version = $post->versions()->first();
$post = $version->revertWithoutSaving();
// soft delete
$post->removeVersion($versionId = 1);
$post->removeVersions($versionIds = [1, 2, 3]);
$post->removeAllVersions();
// force delete
$post->forceRemoveVersion($versionId = 1);
$post->forceRemoveVersions($versionIds = [1, 2, 3]);
$post->forceRemoveAllVersions();
$post->restoreTrashedVersion($id);
// create
Post::withoutVersion(function () use (&$post) {
Post::create(['title' => 'version1', 'content' => 'version1 content']);
});
// update
Post::withoutVersion(function () use ($post) {
$post->update(['title' => 'updated']);
});
You can set the following different version policies through property protected $versionStrategy
:
Overtrue\LaravelVersionable\VersionStrategy::DIFF
- Version content will only contain changed attributes (default strategy).Overtrue\LaravelVersionable\VersionStrategy::SNAPSHOT
- Version content will contain all versionable attribute values.
$diff = $post->getVersion(1)->diff($post->getVersion(2));
$diff
is a object Overtrue\LaravelVersionable\Diff
, it based
on jfcherng/php-diff.
You can render the diff to many formats, and all formats result will be like follows:
[
$attribute1 => $diffOfAttribute1,
$attribute2 => $diffOfAttribute2,
...
$attributeN => $diffOfAttributeN,
]
$diff->toArray();
//
[
"name" => [
"old" => "John",
"new" => "Doe",
],
"age" => [
"old" => 25,
"new" => 26,
],
]
toArray(array $differOptions = [], array $renderOptions = [], bool $stripTags = false): array
toText(array $differOptions = [], array $renderOptions = [], bool $stripTags = false): array
toJsonText(array $differOptions = [], array $renderOptions = [], bool $stripTags = false): array
toContextText(array $differOptions = [], array $renderOptions = [], bool $stripTags = false): array
toHtml(array $differOptions = [], array $renderOptions = [], bool $stripTags = false): array
toInlineHtml(array $differOptions = [], array $renderOptions = [], bool $stripTags = false): array
toJsonHtml(array $differOptions = [], array $renderOptions = [], bool $stripTags = false): array
toSideBySideHtml(array $differOptions = [], array $renderOptions = [], bool $stripTags = false): array
Note
$differOptions
and$renderOptions
are optional, you can set them following the README of jfcherng/php-diff.$stripTags
allows you to remove HTML tags from the Diff, helpful when you don't want to show tags.
You can define $versionModel
in a model, that used this trait to change the model(table) for versions
Note
Model MUST extend class
\Overtrue\LaravelVersionable\Version
;
<?php
class PostVersion extends \Overtrue\LaravelVersionable\Version
{
//
}
Update the model attribute $versionModel
:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Overtrue\LaravelVersionable\Versionable;
class Post extends Model
{
use Versionable;
public string $versionModel = PostVersion::class;
}
- mansoorkhan96/filament-versionable Effortlessly manage revisions of your Eloquent models in Filament.
如果你喜欢我的项目并想支持它,点击这里 ❤️
Many thanks to Jetbrains for kindly providing a license for me to work on this and other open-source projects.
You can contribute in one of three ways:
- File bug reports using the issue tracker.
- Answer questions or fix bugs on the issue tracker.
- Contribute new features or update the wiki.
The code contribution process is not very formal. You just need to make sure that you follow the PSR-0, PSR-1, and PSR-2 coding guidelines. Any new code contributions must be accompanied by unit tests where applicable.
MIT