Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Revisionable Upgrade Laravel Package

fico7489/laravel-revisionable-upgrade

Laravel package for adding revision history to Eloquent models. It tracks changes, stores model snapshots, and lets you view diffs or restore previous versions—an upgraded alternative to older revisionable packages.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install both packages. The upgrade package is an extension, not a replacement:

    composer require venturecraft/revisionable fico7489/laravel-revisionable-upgrade
    

    If Composer complains about version constraints on newer Laravel releases, pin the upgrade to the latest tagged release and allow it via --with-all-dependencies, or add an inline "repositories" / platform override. Treat it as a legacy dependency.

  2. Publish and run the revisionable migration. The upgrade package does not ship its own schema; it reuses the revisions table from venturecraft. Run php artisan vendor:publish --provider="Venturecraft\Revisionable\RevisionableServiceProvider" then php artisan migrate.

  3. Swap the trait on your model. Replace venturecraft's trait with the upgrade trait (it extends the original behaviour):

    use Fico7489\LaravelRevisionableUpgrade\Traits\RevisionableUpgradeTrait;
    
    class Post extends Model
    {
        use RevisionableUpgradeTrait;
    
        protected $revisionable = ['title', 'body', 'status'];
    }
    
  4. Look first at the trait source (vendor/fico7489/laravel-revisionable-upgrade/src/Traits/RevisionableUpgradeTrait.php) and the README's method list. The whole package is a thin set of helpers around venturecraft\Revisionable\RevisionableTrait; reading both traits side-by-side is faster than guessing at method signatures.

  5. First use case: render a per-record audit trail and let an editor roll back a bad change:

    $post->getRevisionHistory();          // collection of Revision rows
    $post->getRevisionByVersion(3);       // specific snapshot
    $post->revertToVersion(3);            // writes a new revision restoring v3
    

Implementation Patterns

Audit-log page (per record). Load history once and join the user relation rather than per-row:

$history = $post->getRevisionHistoryWithUser();
// or eager-load users when you have many records
Post::with('revisionHistory.user')->paginate();

Render revision->created_at, revision->user->name, and the field deltas. Use the revision's own updated_at as the "changed at" timestamp—don't fall back to the model's timestamp.

Version comparison / diff view. The upgrade's value is in the diff helpers. Typical pattern:

$old = $post->getRevisionByVersion($fromVersion);
$new = $post->getRevisionByVersion($toVersion);
$diff = $post->getRevisionDiff($old, $new); // structured old/new pairs

Iterate the diff array into a two-column table. Always guard against null revisions (an unchanged field is simply absent, not an empty string), and treat HTML/JSON columns separately—render them escaped or pretty-printed rather than line-diffing.

Revert workflow. Wrap reverts in a transaction, authorize first, and log who triggered it:

DB::transaction(function () use ($post, $version) {
    $post->revertToVersion($version);
    activity()->on($post)->log("Reverted to v{$version}");
});

Because reverts create a new revision, the operation is itself auditable and idempotent-ish; you never destroy history.

Approval / draft flows. Use getRevisionByDate() when business rules are time-based ("what did this look like at contract signing?"), and getRevisionByVersion() when they're sequence-based ("restore the pre-review draft"). Pin the version number in the workflow record so it survives later edits.

Custom user attribution. If your auth is multi-tenant or uses an API token (no Auth::user()), override the user resolution on the model so revisions don't end up with null user IDs. The venturecraft side exposes this via a resolver method; keep it consistent across all revisionable models.

Displaying the "current" vs "historic". Snapshot models are read-only—don't save them through the normal path, or you'll silently create a new revision on the live row. Expose them as DTOs or a read-only presenter.

Gotchas and Tips

  • Abandonment is the main risk. Last release Sept 2020; it targets the Laravel 5.8–8 era and PHP 7.x. On Laravel 9+/PHP 8.1+ expect deprecation warnings, and test the trait against your exact framework version before committing. If you need something actively maintained, evaluate owen-it/laravel-auditing or fico7489's own laravel-revisionable fork.
  • Trait collision. You must remove/replace the original RevisionableTrait—using both will conflict. If some models need only vanilla behaviour, keep them on venturecraft and put the upgrade trait only where you use versioning/diff helpers.
  • Migration mismatch. If venturecraft shipped new migration columns in a version you didn't pin, getRevisionHistoryWithUser() and diff methods may silently return empty joins. Check the revisions table for user_id, ip_address, and the morph columns.
  • Version numbers are per-record, starting at 1. They are not global IDs. Never treat a version number as stable across records or as a foreign key; use the revision's id for that, and use version only against a specific model instance.
  • Morph maps break type lookups. If you register Relation::morphMap([...]), revisionable_type stores the alias, not the FQCN. Any code that queries revisions by raw class name will miss rows after a morph-map change.
  • Diff method signatures are easy to get wrong. Older docs show passing version integers and newer code passes Revision instances (or vice versa) depending on the tag. Verify against the trait source at the installed version—ReflectionMethod or a quick dump() in tinker is quicker than a Stack Overflow rabbit hole.
  • $revisionable is opt-in per field. A field not listed is never recorded; a field added later has no history before that release. Document this for support teams or they'll file "missing history" tickets.
  • Reverts and soft deletes. Restoring a version of a soft-deleted model does not necessarily undelete it—handle deleted_at explicitly in the revert wrapper if your workflow needs it.
  • Performance. getRevisionHistory() on a collection triggers N+1 queries. Eager-load revisionHistory and its user, and consider a dedicated index on (revisionable_type, revisionable_id, version) for large audit tables.
  • Extension points. Override the revision model class (via the venturecraft config or a getRevisionModel() override) if you need extra columns or scopes; keep the trait untouched so upgrades remain diffable.
  • Debugging recipe. Confirm the trait fires by checking the revisions row immediately after a save; if it's empty, verify the field is in $revisionable, the attribute actually changed (dirty check), and revisionable isn't disabled globally in config.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource