PHPackages                             convenia/revisionable - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. convenia/revisionable

ActiveLibrary[Database &amp; ORM](/categories/database)

convenia/revisionable
=====================

Keep a revision history for your eloquent models without thinking

v2.2(8y ago)912.5k2MITPHPPHP &gt;=5.6

Since Apr 8Pushed 8y ago5 watchersCompare

[ Source](https://github.com/convenia/revisionable)[ Packagist](https://packagist.org/packages/convenia/revisionable)[ Docs](http://github.com/convenia/revisionable)[ RSS](/packages/convenia-revisionable/feed)WikiDiscussions master Synced 2mo ago

READMEChangelog (10)Dependencies (5)Versions (72)Used By (0)

[![logo](revisionable.png)](revisionable.png)

---

Easily create a revision history for any Eloquent model

```
namespace App;

use Convenia\Revisionable\RevisionableTrait;

class Article extends Eloquent {

    use RevisionableTrait;
}
```

And you're good to go!

---

This project is a fork of  with some improvements and new features

The [v1 readme](README_v1.md) is also available if you want to use an old 1.x version

---

[![Packagist](https://camo.githubusercontent.com/ca9419147e10056aa771fb5defdf1f80f7305ff3862cf9746428f5d6129bc915/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f636f6e76656e69612f7265766973696f6e61626c652e737667)](https://packagist.org/packages/convenia/revisionable)[![Build Status](https://camo.githubusercontent.com/9b255b68eeedf48bd0cb1c776510d3b22911af8dd33187c961f5663b801c9b5f/68747470733a2f2f73656d6170686f726563692e636f6d2f6170692f76312f656462697a6172726f2f7265766973696f6e61626c652f6272616e636865732f6d61737465722f62616467652e737667)](https://semaphoreci.com/edbizarro/revisionable) [![StyleCI](https://camo.githubusercontent.com/812c384dff96166b26188b78d67eee78632abb6ef9a6321bea7f8058f8ad5c97/68747470733a2f2f7374796c6563692e696f2f7265706f732f38333733333939352f736869656c643f6272616e63683d6d6173746572)](https://styleci.io/repos/83733995) [![Codacy Badge](https://camo.githubusercontent.com/2d076f1a21c726b460651dd168914c2369cf07690152830af4b8c8d80b041073/68747470733a2f2f6170692e636f646163792e636f6d2f70726f6a6563742f62616467652f47726164652f6534656338383366656135643439373361333037333863356131666666316533)](https://www.codacy.com/app/Convenia/revisionable?utm_source=github.com&utm_medium=referral&utm_content=convenia/revisionable&utm_campaign=Badge_Grade) [![Codacy Badge](https://camo.githubusercontent.com/c14f12bb84620220e897298dcb56da97313e57aeacc09f155403a23e9b147d85/68747470733a2f2f6170692e636f646163792e636f6d2f70726f6a6563742f62616467652f436f7665726167652f6534656338383366656135643439373361333037333863356131666666316533)](https://www.codacy.com/app/Convenia/revisionable?utm_source=github.com&utm_medium=referral&utm_content=convenia/revisionable&utm_campaign=Badge_Coverage) [![Code Climate](https://camo.githubusercontent.com/cf1017901028a4b59a13149bbe31abfb11ca6a43ce79c8624f2c43373c55482b/68747470733a2f2f636f6465636c696d6174652e636f6d2f6769746875622f636f6e76656e69612f7265766973696f6e61626c652f6261646765732f6770612e737667)](https://codeclimate.com/github/convenia/revisionable) [![Packagist](https://camo.githubusercontent.com/5fd3a2c30b56b2b2a0fd9c0de0457d91ce9fc848563fb74898ddb85914f5569e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646d2f636f6e76656e69612f7265766973696f6e61626c652e737667)](https://packagist.org/packages/convenia/revisionable)

Installation
------------

[](#installation)

#### Via [composer](http://getcomposer.org/doc/00-intro.md) (recommended)

[](#via-composer-recommended)

```
composer require convenia/revisionable:^2.0

```

Next, you must install the service provider:

```
// config/app.php
'providers' => [
    ...
    Convenia\Revisionable\RevisionableServiceProvider::class,
];
```

You can publish the migration with:

```
php artisan vendor:publish --provider="Convenia\Revisionable\RevisionableServiceProvider" --tag="migrations"

```

After the migration has been published you can create the revisions table by running the migrations:

```
php artisan migrate

```

Docs
----

[](#docs)

- [Implementation](#implementation)
    - [Soft deletes](#soft)
    - [Creation](#create)
- [Contributing](#contributing)

Implementation
--------------

[](#implementation)

```
namespace App;

use Convenia\Revisionable\RevisionableTrait;

class Article extends Eloquent {

    use RevisionableTrait;
}
```

If needed, you can disable the revisioning by setting `$revisionEnabled` to false in your model. This can be handy if you want to temporarily disable revisioning, or if you want to create your own base model that extends revisionable, which all of your models extend, but you want to turn revisionable off for certain models.

```
namespace App;

use Convenia\Revisionable\RevisionableTrait;

class Article extends Eloquent {

    use RevisionableTrait;

    protected $revisionEnabled = false;
}
```

You can also disable revisioning after X many revisions have been made by setting `$historyLimit` to the number of revisions you want to keep before stopping revisions.

```
namespace App;

use Convenia\Revisionable\RevisionableTrait;

class Article extends Eloquent {

    use RevisionableTrait;

    protected $historyLimit = 500; //Stop tracking revisions after 500 changes have been made.
}
```

In order to maintain a limit on history, but instead of stopping tracking revisions if you want to remove old revisions, you can accommodate that feature by setting `$revisionCleanup`.

```
namespace App;

use Convenia\Revisionable\RevisionableTrait;

class Article extends Eloquent {

    use RevisionableTrait;

    protected $revisionCleanup = true; //Remove old revisions (works only when used with $historyLimit)
    protected $historyLimit = 500; //Maintain a maximum of 500 changes at any point of time, while cleaning up old revisions.
}
```

You can suspend or set the revision temporarily by calling the methods withourRevision() and withRevision().

```
    Article::withoutRevision();
    $article = Article::create(['title' => 'Amazing Article']);
    $article->title = 'New amazing Article';
    $article->save();
    ...
    Article::withRevision();
    $article->body = 'Text body of an amazing article';
    $article->save();
```

However, this doesn't overrides the revisionEnabled variable. If you call the method withRevision() in a Model that has setted $revisionEnabled = false, the revision will not occur.

### Divergent column and model names

[](#divergent-column-and-model-names)

Sometimes a model can have a relationship in which the column associated doesn't follow the eloquent pattern, being needed to specify the foreign. In these cases, you need to declare an array called divergentRelations, where the column name points to the model name, in lowercase. This makes possible to query the relationship field value (like name or title), when using the methods newValue or oldValue on the revision

```
class Article extends Model
{
    public $divergentRelations = [
        'quoted_id' => 'quotedauthors',
    ];
    public function quotedAuthors()
    {
        return $this->belongsTo(QuotedAuthors::class, 'quoted_id');
    }
}

class QuotedAuthor extends Model
{
    public function articles()
    {
        return $this->hasMany(Article::class);
    }
}

    ...
    $newQuotedAuthor = QuotedAuthor::create(['name' => 'New Quoted Author']);
    $article->quoted_id = $newQuotedAuthor->id;
    $article->save();
    $revision = $article->revisionHistory()->first();
    $revision->newValue() = 'New Quoted Author';
```

If you don't set the array $divergentRelations and tries to get the revision newValue, you would get the id instead of the name or title;

```
class Article extends Model
{
    public function quotedAuthors()
    {
        return $this->belongsTo(QuotedAuthors::class, 'quoted_id');
    }
}

class QuotedAuthor extends Model
{
    public function articles()
    {
        return $this->hasMany(Article::class);
    }
}

    ...
    $newQuotedAuthor = QuotedAuthor::create(['name' => 'New Quoted Author']);
    $article->quoted_id = $newQuotedAuthor->id;
    $article->save();
    $revision = $article->revisionHistory()->first();
    $revision->newValue() = 1 ;
```

### Storing soft deletes

[](#storing-soft-deletes)

By default, if your model supports soft deletes, revisionable will store this and any restores as updates on the model.

You can choose to ignore deletes and restores by adding `deleted_at` to your `$dontKeepRevisionOf` array.

To better format the output for `deleted_at` entries, you can use the `isEmpty` formatter (see [Format output](#format-output) for an example of this.)

### Storing creations

[](#storing-creations)

By default the creation of a new model is not stored as a revision. Only subsequent changes to a model is stored.

If you want to store the creation as a revision you can override this behavior by setting `revisionCreationsEnabled` to `true` by adding the following to your model:

```
protected $revisionCreationsEnabled = true;
```

Format output
-------------

[](#format-output)

> You can continue (and are encouraged to) use `eloquent accessors` in your model to set the output of your values, see the [laravel docs for more information on accessors](http://laravel.com/docs/eloquent-mutators#accessors-and-mutators)The below documentation is therefor deprecated

In cases where you want to have control over the format of the output of the values, for example a boolean field, you can set them in the `$revisionFormattedFields` array in your model. e.g.,

```
protected $revisionFormattedFields = array(
    'title'  => 'string:%s',
    'public' => 'boolean:No|Yes',
    'modified' => 'datetime:m/d/Y g:i A',
    'deleted_at' => 'isEmpty:Active|Deleted'
);
```

You can also override the field name output using the `$revisionFormattedFieldNames` array in your model, e.g.,

```
protected $revisionFormattedFieldNames = array(
    'title' => 'Title',
    'small_name' => 'Nickname',
    'deleted_at' => 'Deleted At'
);
```

This comes into play when you output the revision field name using `$revision->fieldName()`

### String

[](#string)

To format a string, simply prefix the value with `string:` and be sure to include `%s` (this is where the actual value will appear in the formatted response), e.g.,

```
string:%s

```

### Boolean

[](#boolean)

Booleans by default will display as a 0 or a 1, which is pretty bland and won't mean much to the end user, so this formatter can be used to output something a bit nicer. Prefix the value with `boolean:` and then add your false and true options separated by a pipe, e.g.,

```
boolean:No|Yes

```

### DateTime

[](#datetime)

DateTime by default will display as Y-m-d H:i:s. Prefix the value with `datetime:` and then add your datetime format, e.g.,

```
datetime:m/d/Y g:i A

```

### Is Empty

[](#is-empty)

This piggy backs off boolean, but instead of testing for a true or false value, it checks if the value is either null or an empty string.

```
isEmpty:No|Yes

```

This can also accept `%s` if you'd like to output the value, something like the following will display 'Nothing' if the value is empty, or the actual value if something exists:

```
isEmpty:Nothing|%s

```

Contributing
------------

[](#contributing)

Contributions are encouraged and welcome; to keep things organised, all bugs and requests should be opened in the GitHub issues tab for the main project, at [convenia/revisionable/issues](https://github.com/convenia/revisionable/issues)

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity26

Limited adoption so far

Community24

Small or concentrated contributor base

Maturity73

Established project with proven stability

 Bus Factor1

Top contributor holds 51.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~25 days

Recently: every ~33 days

Total

66

Last Release

3158d ago

Major Versions

1.29.5 → v2.02017-03-02

PHP version history (2 changes)1.0.2PHP &gt;=5.3.0

v2.0PHP &gt;=5.6

### Community

Maintainers

![](https://www.gravatar.com/avatar/8d6c4d98b8ee2e111badaf700c0fea0555fe1a61db36940f6a65d82aed61795d?d=identicon)[euventura](/maintainers/euventura)

---

Top Contributors

[![duellsy](https://avatars.githubusercontent.com/u/330539?v=4)](https://github.com/duellsy "duellsy (178 commits)")[![edbizarro](https://avatars.githubusercontent.com/u/84926?v=4)](https://github.com/edbizarro "edbizarro (94 commits)")[![euventura](https://avatars.githubusercontent.com/u/378751?v=4)](https://github.com/euventura "euventura (13 commits)")[![sniper7kills](https://avatars.githubusercontent.com/u/5902574?v=4)](https://github.com/sniper7kills "sniper7kills (10 commits)")[![stierler](https://avatars.githubusercontent.com/u/1009070?v=4)](https://github.com/stierler "stierler (8 commits)")[![GrahamCampbell](https://avatars.githubusercontent.com/u/2829600?v=4)](https://github.com/GrahamCampbell "GrahamCampbell (6 commits)")[![anarchocoder](https://avatars.githubusercontent.com/u/8037302?v=4)](https://github.com/anarchocoder "anarchocoder (6 commits)")[![argia-andreas](https://avatars.githubusercontent.com/u/9297340?v=4)](https://github.com/argia-andreas "argia-andreas (4 commits)")[![RDelorier](https://avatars.githubusercontent.com/u/2295675?v=4)](https://github.com/RDelorier "RDelorier (3 commits)")[![trizz](https://avatars.githubusercontent.com/u/832056?v=4)](https://github.com/trizz "trizz (2 commits)")[![paulofreitas](https://avatars.githubusercontent.com/u/667360?v=4)](https://github.com/paulofreitas "paulofreitas (2 commits)")[![rhynodesigns](https://avatars.githubusercontent.com/u/2198266?v=4)](https://github.com/rhynodesigns "rhynodesigns (2 commits)")[![tauanlemos](https://avatars.githubusercontent.com/u/17324672?v=4)](https://github.com/tauanlemos "tauanlemos (2 commits)")[![luizreginaldo](https://avatars.githubusercontent.com/u/1282758?v=4)](https://github.com/luizreginaldo "luizreginaldo (1 commits)")[![miclf](https://avatars.githubusercontent.com/u/3188746?v=4)](https://github.com/miclf "miclf (1 commits)")[![mmawdsleyhallnet](https://avatars.githubusercontent.com/u/62430199?v=4)](https://github.com/mmawdsleyhallnet "mmawdsleyhallnet (1 commits)")[![orthographic-pedant](https://avatars.githubusercontent.com/u/14522744?v=4)](https://github.com/orthographic-pedant "orthographic-pedant (1 commits)")[![teaqu](https://avatars.githubusercontent.com/u/583418?v=4)](https://github.com/teaqu "teaqu (1 commits)")[![rajivseelam](https://avatars.githubusercontent.com/u/1103649?v=4)](https://github.com/rajivseelam "rajivseelam (1 commits)")[![ivelrrat](https://avatars.githubusercontent.com/u/5580032?v=4)](https://github.com/ivelrrat "ivelrrat (1 commits)")

---

Tags

auditeloquenthistorylaravelrevisionrevision-historyrevisionablelaravelmodelrevisionhistory

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/convenia-revisionable/health.svg)

```
[![Health](https://phpackages.com/badges/convenia-revisionable/health.svg)](https://phpackages.com/packages/convenia-revisionable)
```

###  Alternatives

[venturecraft/revisionable

Keep a revision history for your models without thinking, created as a package for use with Laravel

2.6k6.6M51](/packages/venturecraft-revisionable)[mpociot/versionable

Allows to create Laravel 4 / 5 / 6 / 7 / 8 / 9 / 10 / 11 Model versioning and restoring

7841.1M6](/packages/mpociot-versionable)[panoscape/history

Eloquent model history tracking for Laravel

162130.3k](/packages/panoscape-history)[highsolutions/eloquent-sequence

A Laravel package for easy creation and management sequence support for Eloquent models with elastic configuration.

121130.3k](/packages/highsolutions-eloquent-sequence)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
