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 Drafts Laravel Package

oddvalue/laravel-drafts

Drop-in drafts and revisions for Laravel Eloquent models. Create, save, publish, and preview revisions with a simple API, middleware support, and minimal setup—ideal for CMS-style editing workflows without building a custom versioning system.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:
    composer require oddvalue/laravel-drafts
    php artisan vendor:publish --tag="drafts-config"
    
  2. Add Trait to Model:
    use Oddvalue\LaravelDrafts\Concerns\HasDrafts;
    
    class Post extends Model
    {
        use HasDrafts;
    }
    
  3. Run Migration:
    Schema::table('posts', function (Blueprint $table) {
        $table->drafts();
    });
    

First Use Case

Create a draft post:

$post = Post::createDraft(['title' => 'Draft Post', 'content' => 'Draft content']);

Publish it:

$post->publish();

Implementation Patterns

Core Workflows

  1. Draft Creation & Management:

    • Use createDraft() for new drafts.
    • Use saveAsDraft()/updateAsDraft() for existing records.
    • Example:
      $post = Post::find(1);
      $post->updateAsDraft(['title' => 'Updated Draft']);
      
  2. Revisions Handling:

    • Fetch revisions:
      $revisions = Post::find(1)->revisions()->get();
      
    • Update without creating a revision:
      $post->withoutRevision()->update(['title' => 'No Revision']);
      
  3. Preview Mode:

    • Enable for admin interfaces:
      \Oddvalue\LaravelDrafts\Facades\LaravelDrafts::previewMode();
      
    • Disable for public:
      \Oddvalue\LaravelDrafts\Facades\LaravelDrafts::disablePreviewMode();
      

Integration Tips

  1. Middleware for Draft Access:

    Route::withDrafts(function () {
        Route::get('/admin/posts', [PostController::class, 'index']);
    });
    
  2. Handling Relations:

    • Define draftable relations:
      protected $draftableRelations = ['tags', 'author'];
      
    • Package handles syncing relations on publish.
  3. Custom Column Names:

    • Override via constants:
      public const IS_CURRENT = 'is_editing';
      
  4. Query Scopes:

    • Fetch all drafts:
      Post::onlyDrafts()->get();
      
    • Fetch current revisions:
      Post::current()->get();
      

Gotchas and Tips

Common Pitfalls

  1. Relation Syncing:

    • Only HasOne, HasMany, BelongsToMany, and MorphToMany relations are supported. Ensure $draftableRelations is set correctly.
  2. Preview Mode Scope:

    • Forgetting to disable preview mode in production can expose drafts to the public.
  3. Revision Limits:

    • Default keeps 10 revisions. Adjust in config/drafts.php:
      'revisions' => ['keep' => 20],
      
  4. Soft Deletes:

    • Soft-deleting a model also soft-deletes its revisions. Use forceDelete() to bypass this.

Debugging Tips

  1. Check Current Revision:

    $post->isCurrent(); // Returns true if the record is the current draft
    
  2. Verify Draft State:

    $post->isDraft(); // Returns true if unpublished
    
  3. Inspect Revisions:

    $post->revisions()->orderBy('created_at', 'desc')->get();
    

Extension Points

  1. Customize Revision Behavior:

    • Override shouldCreateRevision() in your model:
      protected function shouldCreateRevision(): bool
      {
          return !request()->has('skip_revision');
      }
      
  2. Modify Publish Logic:

    • Override publish() method to add custom logic before publishing.
  3. Event Listeners:

    • Listen for drafts.published or drafts.created events:
      event(new \Oddvalue\LaravelDrafts\Events\Published($post));
      

Configuration Quirks

  1. Column Name Conflicts:

    • Ensure custom column names (e.g., IS_CURRENT) don’t conflict with existing model attributes.
  2. Auth Guard:

    • Verify the auth.guard in config matches your application’s guard (default: web).
  3. UUID Generation:

    • Uses Laravel’s Str::uuid(). Ensure your database supports UUID fields.

Performance Considerations

  1. Large Datasets:

    • Use withDrafts(false) or onlyDrafts() to limit query scope when fetching many records.
  2. Relation Loading:

    • Eager-load draftable relations to avoid N+1 queries:
      Post::withDrafts()->with(['tags', 'author'])->get();
      
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.
hamzi/corewatch
minionfactory/raw-hydrator
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