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

Eloquent Draftable Laravel Package

optix/eloquent-draftable

A Laravel package that adds draft and published states to Eloquent models, letting you save work-in-progress records and publish them later. Drafts stay separate from live content, so unfinished entries remain hidden from your application's normal queries until you're ready.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • Addresses a well-understood domain problem: staged content revisions with an explicit publish step. Common in CMS, marketing pages, product catalogs, and policy/config content.
  • The package is a trait + migration hybrid, meaning it imposes a schema convention on host models rather than living purely at the query layer. That is the main architectural commitment — it is not a drop-in decorator you can swap out cheaply later.
  • Suitable for monoliths and modular monoliths with a single write path. Poor fit for event-sourced or CQRS designs, where draft state should live in the domain model rather than as shadow rows.
  • Does not appear to address multi-author concurrency, review workflows, or scheduled publishing. If the roadmap includes editorial approval or time-based release, this package covers maybe 30% of that surface.

Integration feasibility

  • Standard Composer install with Laravel auto-discovery; typically requires publishing a migration and adding a column or companion table.
  • v2.1.0 changes the install matrix: it now targets Laravel 8 and requires PHP ≥ 7.3 (PHP 7.2 dropped). This confirms the package's compatibility ceiling sits at Laravel 8 / PHP 7.3–8.1. It does not add Laravel 9/10/11/12 or PHP 8.2+.
  • Effort to a working prototype: low (half a day) on a Laravel 8 host. Effort to a production-grade rollout: moderate — the cost is in backfill, indexing, and reconciling relations, not in wiring the trait.
  • Blocking constraint remains framework version, not API complexity. On a modern stack the package still resolves to a hard conflict.

Technical risk

  • Primary risk: effective abandonment — slightly reduced, not resolved. v2.1.0 demonstrates one additional release and some maintainer attention, so the risk of a dead package is marginally lower than assessed previously. However, the release only reaches Laravel 8, which itself reached EOL in January 2023. The project's compatibility window has not moved forward; it has confirmed a ceiling in the 2021 era. Treat this as a signal of low, not active, maintenance.
  • Zero dependents and low star count (reported 27) still means no ecosystem validation, no third-party bug reports, and no observable production usage to learn from. One release does not create a user base.
  • Score 0.415 is consistent with the above: functionally plausible, operationally unproven. The v2.1.0 release is a small positive on liveness but does not materially move the operational confidence component.
  • Bus-factor risk: maintained (or formerly maintained) by a single agency, with no visible governance, security policy, or issue-triage cadence.
  • Behavioral risk: draft/publish semantics interact with Eloquent events, observers, unique constraints, and relation syncing in ways that are easy to get subtly wrong and hard to test for.

Key questions (to resolve before any commitment)

  1. What exact illuminate/* and php constraints does v2.1.0 declare, and does it install cleanly on our target Laravel and PHP versions? (Confirm it does not merely widen to Laravel 8 while locking PHP below our baseline.)
  2. Is the draft stored as a self-referencing row, a polymorphic companion table, or parallel columns? This determines migration cost and query complexity.
  3. How are belongsToMany, hasMany, and media/attachment relations handled on a draft — copied, shared, or unsupported?
  4. What happens on publish — does it mutate the draft into the canonical row, copy fields, or swap a pointer? Pointer-swap is cleanest; field-copy is lossy.
  5. Does publish fire model events and invalidate caches/observers, or does it bypass them via query builder?
  6. Are UUID/ULID primary keys supported, or does it assume auto-increment integers?
  7. Interaction with soft deletes, updated_at semantics, and global scopes — are drafts excluded from default queries?
  8. Is there any test suite in the repo, and does it pass on our CI matrix? Did v2.1.0 add or change tests?
  9. License is MIT — confirmed clean for commercial use, no attribution burden. (Verified.)
  10. Is there an actively maintained alternative with comparable ergonomics that we should benchmark against first?

Integration Approach

Stack fit

  • Viable on Laravel ≤ 8 with PHP 7.3–8.1. On Laravel 9+ expect a hard Composer conflict. v2.1.0 widens the floor for PHP to 7.3 but does not raise the framework ceiling.
  • If our stack is modern (Laravel 10/11/12, PHP 8.2+), the realistic options are unchanged: (a) fork and maintain, (b) vendor the trait source into our codebase and drop the dependency, or (c) build first-party.
  • Given 0 dependents and a single-purpose trait, option (b) — vendoring ~a few hundred lines under our own namespace with our own tests — is often cheaper than carrying a fork and is the option I would default to evaluating. The v2.1.0 release is small enough that a vendor-and-patch approach remains low-effort.

Migration path (if we proceed)

  1. Add nullable draft-linkage column (or companion table) plus an index on the parent key and on the published/draft discriminator.
  2. Backfill existing rows into a known state — every legacy row must be unambiguously "published," or downstream reads break.
  3. Dual-write behind a feature flag: writes go through both the old and new paths; reads stay on the old path.
  4. Add a reconciliation job that asserts exactly one published row per logical entity.
  5. Cut reads over per-model, starting with the lowest-traffic model.

Compatibility

  • Verify DB support for MySQL 8, PostgreSQL 14+, and SQLite (test suite). Self-referencing FKs with cascade rules differ across engines.
  • Verify behavior under DB::transaction, model observers, and queued jobs that hydrate models — draft rows leaking into background workers is a classic failure.
  • Check whether published/draft scoping is a global scope (implicit, risky) or an explicit query method (safer).
  • Confirm the v2.1.0 composer.json constraints against our dependency graph before writing any migration.

Sequencing

  • Weeks 0–1: dependency spike on the real stack, pinned to v2.1.0. If it does not install, stop and re-plan — do not burn time patching blindly. This spike now has a concrete target version to test.
  • Week 1: read the source end-to-end (it is small) and write a characterization test suite covering publish, re-draft, delete, and relation behavior.
  • Week 2: decide fork vs. vendor vs. build. Document the decision and the exit cost.
  • Weeks 3–4: schema migration and backfill on one low-risk model behind a flag.
  • Week 5+: expand model by model, with a reconciliation monitor in place before the third model.

Operational Impact

Maintenance

  • Assume we own this code from day one. The v2.1.0 release is a data point of liveness but not a support commitment; budget this as an internal component, not a dependency.
  • Realistic ownership cost: low per-year in steady state (small surface area), high in the first quarter (test suite, upgrade path, documentation of semantics).
  • Every Laravel major upgrade becomes our problem. v2.1.0 stops at Laravel 8, so any move to Laravel 9+ is a maintenance event for us, not an upstream one. Budget a spike per major version.

Support

  • No vendor SLA, no maintainer response expectation, no security disclosure process. Treat CVEs as “we find them, we fix them.”
  • No community to lean on: coverage for a low-star package is effectively nil. Internal documentation is mandatory, not optional.
  • Onboarding documentation should cover the draft/publish state machine explicitly — that is the part engineers will get wrong.

Scaling

  • Storage: draft rows roughly double row count for draftable entities. Negligible for content, material for high-cardinality catalogs.
  • Query cost: every read path must filter drafts. Missing a filter is a correctness bug, not a performance one, and it will surface in production. Enforce via a repository/scope pattern rather than relying on discipline.
  • Write contention: publish operations that swap pointers need row-level locking; concurrent publish from two editors is a real race in editorial teams.
  • N+1 risk grows because draft and published rows both hydrate relations; eager-loading strategy must be explicit.

Failure modes (ranked by likelihood × impact)

  1. Composer resolution failure on upgrade — high likelihood, blocks CI. Mitigation: vendor the source. v2.1.0 does not change this for modern stacks.
  2. Draft rows leaking into public reads — high impact, user-visible. Mitigation: explicit scopes + integration tests on every read endpoint.
  3. Silent divergence of relations on publish — draft has updated belongsToMany pivots that publish does not apply. High impact, hard to detect.
  4. Unique constraint collision — draft slug collides with published slug on the same table. Fails at write time, blocks editors.
  5. Orphaned drafts after parent delete, depending on FK cascade configuration.
  6. Cache staleness — publish path bypasses observers, caches not invalidated, stale content served.
  7. Concurrent editor race — last-write-wins on publish with no optimistic locking.

Ramp-up

  • API surface is small (trait methods plus a migration); a competent Laravel engineer is productive in under a day.
  • The real ramp-up cost is in the semantics, not the API: when drafts are created, what publish does to relations, and which queries must exclude drafts. Allocate half a day of deliberate documentation and a short design review before the second model adopts it.
  • Recommend a single “owner” engineer for the vendored/forked copy so upgrade decisions have a clear decision-maker. Note in the handoff that v2.1.0 is the terminal upstream state unless the maintainers resume forward porting.
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.
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names