oddvalue/laravel-drafts
A simple, drop-in drafts and revisions system for Laravel models. Add a trait to your model, update the database, and get published revisions, current revisions, auto drafts, and preview mode via middleware, with minimal changes to your existing code.
schedulePublishing() + drafts:publish artisan command on the scheduler), autosave/draft recovery (opt-in auto drafts, quietly upserted in place and excluded from revision history), and preview mode (a facade flag that flips the default scope to current-revision regardless of publish state). Each can ship independently and each is off by default, so we can commit to a date without committing to the whole surface.uuid. This has product consequences worth deciding deliberately: search indexes, sitemaps, analytics counts, exports, and reporting must all exclude non-published rows; storage grows with edit frequency, bounded by the retention setting. If we run a search engine or data warehouse, the sync job needs a publish filter.publisher morph) but not approval state. If the roadmap includes draft → review → approved → publish, or editor/approver role separation, that is custom work on top — budget it separately rather than assuming it is included.revisions(), but a documented "restore this revision" affordance is not part of the stated API. If stakeholders expect one-click revert, treat it as a small build item; if they expect field-level legal-grade audit history, treat it as a different product decision entirely.is_auto or will_publish_at until enabled, and the API throws a LogicException when off. That is a genuinely low-risk way to trial a roadmap item in production.Adopt when most of these hold:
is_current, is_published, is_auto, published_at, uuid, publisher_type, publisher_id (plus will_publish_at if scheduling), added via $table->drafts() and removable via dropDrafts() — a clean migration path, and column names are overridable per model via constants.withDrafts() / onlyDrafts() / current().HasOne/HasMany are duplicated on publish, BelongsToMany/MorphToMany are synced, and you must declare $draftableRelations. Fine for a post/tags model; thin for deep content graphs.Look elsewhere when:
Draftable contract. New models should implement it now to avoid the migration.For executives (one paragraph). We need drafts, publishing, and revision history for content. Building that ourselves is roughly two to four engineering sprints of undifferentiated work plus permanent maintenance. oddvalue/laravel-drafts is a focused, MIT-licensed Laravel package that provides it as a drop-in on our existing models — including scheduled publishing, autosave-based draft recovery, revision retention, and a preview mode that lets non-technical stakeholders review unpublished content via a link. Cost is a composer dependency and an additive database migration; there is no new service, no vendor contract, and it is reversible (the migration helper has a matching drop method). The trade-offs are honest ones: it is an infrastructure layer with no admin interface, it assumes simple content models, and it is maintained by a single author, so we should confine it to content paths rather than revenue-critical flows.
For engineering (the short version). Add HasDrafts (and implement Draftable now, ahead of the next major), run $table->drafts(), declare $draftableRelations. Be aware that the trait installs a global scope returning published rows only — audit every existing query and admin list on those models; opt in explicitly with withDrafts(), onlyDrafts(), current(), or the WithDraftsMiddleware / Route::withDrafts() helper for management routes. Publishing duplicates HasOne/HasMany and syncs pivot relations; revisions cap at 10 by default and cascade on delete/soft-delete/restore; withoutRevision() exists for metadata-only updates. Auto drafts and scheduled drafts are opt-in flags — enabling them on existing tables requires adding is_auto and will_publish_at first, and the related APIs throw until enabled, so they cannot silently affect current behavior. Scheduled publishing needs PublishScheduledDrafts registered per model in the scheduler. The main risks to size in the estimate are: search-index and analytics filtering, any per-revision restore UI we decide to build, and the absence of approval-state and localization support.
How can I help you explore Laravel packages today?