Save a history of your model edits. Storage format inspired by, and probably compatible with, makasim/datadiff.
datadiff-laravel was developed for Laravel 4.2 in mind. Your mileage with Laravel 5+ may vary.
This package uses ElasticSearch as a storage solution. We recommend setting up a separate index to hold the diffs since their format may conflict with things like Elasticquent.
composer require sleavely/datadiff-laravel
Next, we'll need to tell Laravel we exist. In your config/app.php
:
<?php
return array(
// ...
'providers' => array(
// ...
'Sleavely\Datadiff\Providers\DatadiffServiceProvider',
),
// ...
'aliases' => array(
// ...
'Datadiff' => 'Sleavely\Datadiff\Facades\DatadiffFacade',
),
);
Next, we'll configure storage. Running php artisan config:publish sleavely/datadiff
will place the following in app/config/packages/sleavely/datadiff/config.php
:
<?php
return array(
'storage' => 'elasticsearch',
'elasticsearch' => array(
'hosts' => array(
'localhost:9200'
),
'index' => 'datadiffs',
),
);
In your app/start/global.php
, add the following, for each model you wish to store diffs for:
<?php
// ...
MyEloquentPostModel::observe(new \Sleavely\Datadiff\DatadiffObserver);
MyEloquentCommentModel::observe(new \Sleavely\Datadiff\DatadiffObserver);
And in the model:
<?php
class MyEloquentPostModel extends Eloquent {
use \Sleavely\Datadiff\DatadiffTrait;
}
Because we added the DatadiffTrait to our model, we can do cool stuff like:
$post = Post::find(123);
$version = $post->diff_version; // 3, there are two older versions
$latestCommit = $post->diff(); // Returns latest version commit
$firstCommit = $post->diff(1); // Fetch version 1
$newPost = new Post;
$newPost->diff_version; // null
$newPost->diff(); // null
A commit object looks like:
{
"data": {
"id": 123,
"title": "my post",
"body": "foo",
"created_at": "2015-07-21T02:56:47+00:00",
"updated_at": "2015-07-21T02:56:47+00:00"
},
"diff": [],
"meta": {
"my_custom_property": "hello world!"
}
}
You can append data by setting the diff_meta
property on an Eloquent model before saving:
<?php
$post = Post::find(123);
$post->diff_meta = [
'my_custom_property' => 'hello world!',
'author_id' => Auth::user()->id,
];
$post->save();
If you dont want to set diff_meta every time, you can declare your own accessor to automatically set the metadata for the commit:
<?php
class MyEloquentPostModel extends Eloquent {
use \Sleavely\Datadiff\DatadiffTrait;
public function getDiffMetaAttribute($value)
{
return [
'my_custom_property' => 'hello world!',
'author_id' => Auth::user()->id,
];
}
}
You can generate a diff for two arrays with the static compare
method provided by the Datadiff facade.
Objects that implement ArrayableInterface are okay too. :)
$obj1 = Post::find(111);
$obj2 = Post::find(222);
$diff = Datadiff::compare($obj1, $obj2);
The comparison is made with mikemccabe/json-patch-php and returns an array with JSON Patch operations.
I recommend the autonomous package benjamine/jsondiffpatch for showing diffs. At it's core, this is all you'll have to do:
var commits = "Datadiff::getCommits($model->getTable(), $model->getAttribute($model->getKeyName())) in PHP";
var i = commits.length - 1;
var diffdelta = jsondiffpatch.diff(
commits[i - 1].data,
commits[i].data
);
var left = undefined;
// left is optional, if specified unchanged values will be visible too
left = commits[i - 1].data;
document.getElementById('diff').innerHTML = jsondiffpatch.formatters.html.format(diffdelta, left);
Pull requests are appreciated and encouraged!
composer update --dev
All tests extend Sleavely\Datadiff\Tests\TestCase
. To run the suite:
vendor/bin/phpunit