Keeping revisions of your laravel model data

There’s times where you want to be able to keep a revision history of all the changes that are made to your models, whether it be for accountability reasons or for providing the ability to roll back changes.

In our case, it was both, so I decided to make something generic that would let me to pick and choose which of my models I wanted to have a revision history, and when I decided I wanted one to have a revision history it had to be childs play to add on.

The best option to me seemed to make a new base model, which I would extend from any models I wanted to be revision-able, which lead to creating and naming the package, Revisionable.

It’s pretty simple in the way that it works, basically it compares the models data before and after saving it (to help with getting hooks to the before save and after save timing, I made use of another existing package, Ardent).

If any of the values in the model have changed, a record is inserted into the revisionable table making a note of the model type, id, field name, old value, new value, and the timer hat it occurred.

So now, every time a model is changed that is extending the revisionable model, its revision history is stored, and all I have to do is extend the class, that’s it.

The next step though is to pull that data back out of the database at will.

The package comes with another basic revision model which is what is returned when you ask for a revision history. Since we’re extending the revisionable base model from a range of different models, and we want to keep things quick and easy to setup, it doesn’t make sense to have to add in methods into our models for creating the relationships between models, that’s where Laravels awesome morph functionality comes into play.

public function revisionHistory()
{
return $this->morphMany('\Venturecraft\Revisionable\Revision', 'revisionable');
}

Having the above in the base revisionable model, lets us then do things like this:

@foreach($user->revisionHistory as $history)
<li>{{ ucfirst($history->key) }} changed from {{ $history->old_value }} to {{ $history->new_value }}</li>
@endforeach

Which would give you something like:

  • username changed from bob to bobby
  • age changed from 21 to 22
  • city changed from Melbourne to Sydney

You can get the package from packagist here, or feel free to contribute to the github repo to extend it further, there’s still a bit of work to do on it to make it pure schmick.

  • Pingback: Laravel 4 learnings: week 3 | Dries Vints

  • Ryan White

    Hi Chris

    I see you used Ardent originally, and extended that. I’m using Ardent at the moment, and would really like to use Revisionable. How do I go about that?

    My guess is that I’d have to mess with the definition of Revisionable’s class or something, but wouldn’t know where to begin.

    Could you release some info, so folks in my situation could tweak Revisionable to work side by side with Ardent?

    Any help on this would be great.
    Thanks
    Ryan

  • Kuldip

    Hello Chris,

    I want to save Foreign key values into revisions table. How can I do that?

    I can able to save one field from one Model but when I display values from other Model using relations ship then I am not able to Save. I have Country combo box and I have to save it.

    I am newbie, please explain in detail.

    Thanks,
    Kuldip

    • http://www.subooa.com.au Chris Duell

      Sorry, I’m not sure what the problem seems to be. If you look in the revisions table, the foreign key should be saved if it was changed on the model.

      • Kuldip

        Chris, waiting for your positive reply.

        • http://www.subooa.com.au Chris Duell

          Revisionable does not handle pivot tables, sorry.