Weave Code
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 Revisor Laravel Package

indracollective/laravel-revisor

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require indracollective/laravel-revisor
    

    Publish the migration and config:

    php artisan vendor:publish --provider="IndraCollective\Revisor\RevisorServiceProvider" --tag="migrations"
    php artisan vendor:publish --provider="IndraCollective\Revisor\RevisorServiceProvider" --tag="config"
    

    Run migrations:

    php artisan migrate
    
  2. Enable Revisor for a Model: Use the Revisable trait in your Eloquent model:

    use IndraCollective\Revisor\Traits\Revisable;
    
    class Post extends Model
    {
        use Revisable;
    }
    
  3. First Use Case: Create a draft, publish it, and revise it:

    $post = new Post(['title' => 'Draft Post']);
    $post->save(); // Creates a draft
    
    $post->publish(); // Publishes the draft
    $post->title = 'Updated Post';
    $post->save(); // Creates a revision
    

Where to Look First

  • Documentation: laravel-revisor.indracollective.dev (covers core concepts, API, and Filament integration).
  • Config File: config/revisor.php (customize revision behavior, e.g., soft-deletes, revision limits).
  • Migrations: database/migrations/[timestamp]_create_revisions_table.php (understand the schema for revisions).

Implementation Patterns

Core Workflows

  1. Drafting and Publishing:

    // Create a draft (unpublished)
    $post = Post::create(['title' => 'Draft Title']);
    
    // Publish the draft
    $post->publish(); // Sets `published_at` and marks as live
    
    // Revert to draft
    $post->draft(); // Resets `published_at` and unpublishes
    
  2. Revisions:

    // Get all revisions for a model
    $revisions = $post->revisions()->get();
    
    // Restore a specific revision
    $revision = $post->revisions()->where('revisionable_id', $post->id)->first();
    $post->restore($revision);
    
    // Compare revisions (e.g., for a diff view)
    $diff = $post->revisions()->diff($revision);
    
  3. Soft Deletes: Enable in config (config/revisor.php):

    'soft_deletes' => true,
    

    Then use:

    $post->delete(); // Soft deletes the latest revision
    $post->forceDelete(); // Permanently deletes
    
  4. Querying:

    // Get published posts
    Post::published()->get();
    
    // Get drafts
    Post::drafts()->get();
    
    // Get a specific revision
    $post->revisions()->find(1);
    

Integration Tips

  • FilamentPHP: Use laravel-revisor-filament for a UI:

    composer require indracollective/laravel-revisor-filament
    

    Add to your Filament resources:

    use IndraCollective\Revisor\Filament\Resources\RevisorResource;
    
    RevisorResource::make();
    
  • Events: Listen for revision events (e.g., RevisablePublished, RevisableCreated):

    public function boot()
    {
        \IndraCollective\Revisor\Events\RevisablePublished::subscribe(function ($model) {
            // Log or notify when a model is published
        });
    }
    
  • API Responses: Serialize revisions in API responses:

    $post->append(['revisions' => $post->revisions()->latest()->take(5)->get()]);
    
  • Testing: Use Revisable in feature tests:

    $post = Post::factory()->create();
    $post->publish();
    $this->assertDatabaseHas('posts', ['id' => $post->id, 'published_at' => now()]);
    

Gotchas and Tips

Pitfalls

  1. Revision Limits:

    • By default, Revisor keeps all revisions. Configure limits in config/revisor.php:
      'revision_limits' => [
          'posts' => 10, // Keep only 10 revisions for `Post` models
      ],
      
    • Gotcha: Limits are applied after creation, so you may temporarily exceed the limit during testing.
  2. Soft Deletes Conflict:

    • If your model uses Laravel’s SoftDeletes, ensure config/revisor.php has:
      'soft_deletes' => true,
      
    • Gotcha: Forgetting this will cause delete() to fail silently or behave unexpectedly.
  3. Mass Assignment:

    • Revisor does not automatically protect revisionable_id, revision_number, etc. Add them to $guarded or $fillable explicitly:
      protected $guarded = ['revisionable_id', 'revision_number'];
      
  4. Foreign Key Constraints:

    • The revisions table has a foreign key to your model’s table. If you rename your table, update the migration manually.
  5. Event Order:

    • RevisableCreated fires before RevisablePublished. Use this to set defaults:
      RevisableCreated::subscribe(function ($model) {
          $model->author_id = auth()->id();
      });
      

Debugging

  1. Missing Revisions:

    • Check if the revisions table exists and has the correct schema.
    • Verify the revisionable_type and revisionable_id are set correctly (debug with dd($post->revisions()->toSql())).
  2. Publish/Draft Not Working:

    • Ensure published_at is nullable in your model’s table:
      $table->timestamp('published_at')->nullable();
      
    • Check for custom accessors/modifiers overriding published_at.
  3. Performance:

    • Avoid eager-loading revisions unless necessary (they can bloat queries):
      // Bad: Loads all revisions for every post
      $posts = Post::with('revisions')->get();
      
      // Good: Load revisions only when needed
      $post = Post::find(1);
      if (request()->wantsJson()) {
          $post->load('revisions');
      }
      

Extension Points

  1. Custom Revision Fields: Add custom fields to the revisions table by publishing and modifying the migration:

    php artisan vendor:publish --provider="IndraCollective\Revisor\RevisorServiceProvider" --tag="migrations"
    

    Then extend the Revisable trait or use a service provider to add logic.

  2. Revision Strategies: Override the default revision strategy (e.g., to exclude certain fields):

    class Post extends Model
    {
        use Revisable;
    
        protected $revisionStrategy = \IndraCollective\Revisor\Strategies\ExcludeStrategy::class;
    
        protected $revisionExcludes = ['votes', 'temp_data'];
    }
    
  3. Custom Revision Model: Extend the Revision model to add behavior:

    class CustomRevision extends \IndraCollective\Revisor\Models\Revision
    {
        public function scopeApproved($query)
        {
            return $query->where('approved', true);
        }
    }
    

    Bind it in a service provider:

    \IndraCollective\Revisor\Models\Revision::swap(new \App\Models\CustomRevision());
    
  4. API Resources: Create a custom API resource for revisions:

    namespace App\Http\Resources;
    
    use Illuminate\Http\Resources\Json\JsonResource;
    
    class RevisionResource extends JsonResource
    {
        public function toArray($request)
        {
            return [
                'id' => $this->id,
                'revision_number' => $this->revision_number,
                'changes' => $this->changes,
                'created_at' => $this->created_at,
            ];
        }
    }
    

Pro Tips

  1. Audit Logs: Combine with spatie/laravel-activitylog to track who made revisions:

    use Spatie\Activitylog\LogOptions;
    
    $post->logActivity('updated', new LogOptions(['onlyChanges' => true]));
    
  2. Diff Views: Use laravel-revisor-filament or build a custom Blade view to show revision diffs:

    $diff = $post->revisions()->diff($revision);
    return view('posts.diff', compact('diff'));
    
  3. Bulk Operations: Use Revisable::publishMany() or `Revisable::draftMany

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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai