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

Doctrine State Machine Bundle Laravel Package

kphoen/doctrine-state-machine-bundle

Symfony bundle that integrates the Doctrine finite state machine library, letting you define state machines and transitions in configuration and expose them as container services for clean, testable workflow logic in your PHP applications.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit — poor for a Laravel codebase. Despite sitting in a PHP ecosystem, this is not a Laravel package: it is a Symfony bundle (K-Phoen/DoctrineStateMachineBundle) that attaches finite-state-machine metadata to Doctrine ORM entities and drives transitions from Doctrine lifecycle events. It assumes Symfony's dependency-injection container, bundle registration, symfony/event-dispatcher, and the Doctrine annotation driver. Laravel gives you Eloquent, service providers, and its own event dispatcher — none of which are drop-in surfaces for this bundle. Fit is viable only in the narrow case of an application already running Doctrine ORM 2.x under Laravel (e.g., via laravel-doctrine/orm) and willing to hand-wire the bundle's services.

Integration feasibility — conditional and non-trivial. Prerequisites a TPM must budget for:

Requirement Available in a typical Laravel app?
Doctrine ORM entities No (Eloquent is default)
Symfony DI container / bundle kernel No
Symfony EventDispatcher for the FSM listener Partial (Laravel events ≠ Symfony contracts)
Doctrine annotation mapping (docblock) No on modern stacks; attributes only
Service provider, config publish, Artisan commands None shipped
PHP 8.1+ compatibility Unverified, likely broken

The realistic integration is a custom bridge: a service provider that registers the metadata listener and transition subscriber on Doctrine's EventManager, plus a symfony/event-dispatcher shim. That bridge is more code than the business logic it enables.

Technical risk — high, concentrated in abandonment. Description explicitly marks the package [DEPRECATED]; last release 2016-08-17; 45 stars; 0 dependents on the registry. That combination means no upstream maintainer, no security response path, no PHP 8.x compatibility work, and no community to ask when it breaks. Secondary risks:

  • Lock-in shape: FSM definitions live in entity docblock annotations, which are invisible to grep, hostile to code review, and expensive to migrate later.
  • Failure opacity: a mis-ordered Doctrine listener fails as a missing transition — silent state drift, not an exception.
  • Version ceiling: the dependency graph predates Symfony 4/5 and Doctrine ORM 2.10+, so even a well-maintained host app will hit composer why-not walls quickly.

Key questions for the sponsor:

  1. Do we actually need FSM semantics, or a status column plus guards in a Form Request / policy? (Often the latter.)
  2. Is any service in scope already on Doctrine ORM? If no, this package is out of consideration on day one.
  3. What is the real cost of a ~200–400 line Laravel-native replacement vs. a compatibility bridge plus a vendor fork we must own forever?
  4. Do we need an immutable transition audit log? This bundle does not provide one — that requirement alone pushes toward a custom implementation.
  5. Who owns the fork, and what's the exit trigger (PHP upgrade, security scan finding, first production incident)?

TPM read on the scores: the composite 2.21 is a "do not adopt" signal; the opportunity score of 7.76 should be read as high value in replacing/porting the concept, not as evidence of package quality. The idea — declarative states and transitions enforced at persistence time — is sound and worth 2–3 days of design extraction; the artifact is not.

Integration Approach

Stack fit. This package fits a Symfony 2/3 + Doctrine 2 application circa 2015. In a Laravel context the only coherent placement is a Doctrine-backed bounded context (a reporting, billing, or legacy-integration service that already speaks Doctrine). Do not introduce Doctrine into an Eloquent application to consume this bundle — the ORM migration alone dwarfs any FSM benefit.

Migration path — three options, ranked:

  1. Do not adopt; port the pattern (recommended). Keep the model: states enum, transition table, guard/can() check, single transitionTo() mutator that writes state + emits a domain event in the same transaction. Implement against Eloquent with casts, a HasStateMachine trait, and observers. Cost: small. Risk: low. Gain: identical semantics, PHP 8.1+ native, testable, greppable.
  2. Fork and pin inside a Doctrine service. Clone, add PHP 8 attributes support, pin every transitive dependency, and register the listener manually — no bundle kernel. Only if a service already depends on Doctrine and a status workflow is genuinely blocked.
  3. Substitute the engine, not the bundle. If the team wants declarative config, use a maintained standalone state-machine library (or symfony/workflow operated directly, without the Symfony full stack) and wire it in a Laravel service provider. Note symfony/workflow expects Symfony's event dispatcher and property-access components; verify the standalone footprint before committing.

Compatibility gates before any code is written. Run composer why-not kphoen/doctrine-state-machine-bundle against the target app; confirm (a) Doctrine ORM major, (b) Symfony component versions, (c) PHP constraint, (d) whether the annotation reader is still installed. A single failure here should terminate the spike — no exceptions.

Sequencing.

  • Week 0 — Spike (1–2 days): read the bundle's listener and metadata driver; extract the state/transition model as a written spec; produce a composer compatibility verdict.
  • Week 1 — Build-vs-adopt decision: cost the native trait (~1–2 dev-days) against the bridge + permanent fork ownership (~1 dev-day now, unbounded later). Default to native.
  • Week 2 — Contract definition: enumerate states, transitions, guards, side effects, and who may trigger each; define the audit record (actor, from, to, reason, timestamp).
  • Week 3 — Implementation & backfill: ship the native trait, migrate any existing status columns, add a one-off script to normalize unknown values.
  • Week 4 — Hardening: property-based tests over the transition matrix (illegal transitions must throw), concurrency test with parallel writers, and a Graphviz dump of the machine checked into docs (this bundle's one genuinely good idea — reuse it).

Operational Impact

Maintenance. If adopted, this becomes a permanent fork: abandoned packages are flagged by Composer's audit tooling and by SBOM/security scanners, which will surface as a recurring compliance finding in every release review. Budget for a named owner, a pinned lockfile, and a documented exit plan. The 2016 vintage means any PHP or framework upgrade re-opens the fork work; expect this to recur annually.

Support. No upstream, no maintainer, no issue triage. Answers exist only in 2014–2016 Stack Overflow and the README. Internal onboarding must rely on the extracted spec, not the code — another argument for writing the spec regardless of the decision.

Scaling. The FSM evaluation itself is cheap (in-memory state graph, negligible CPU per entity). Two real concerns:

  • Flush-time coupling: transitions resolve during Doctrine's onFlush/postLoad, so cost scales with the unit of work, not the request — batch imports become hard to reason about.
  • Graphviz dumping is dev/documentation-only; never invoke it on a request path.

The dominant scaling risk is organizational, not computational: one under-maintained dependency in the persistence hot path.

Failure modes to instrument for:

Failure Symptom Detection
Listener not registered Transitions silently no-op; state never changes Assert state delta on every write in tests
Listener ordering Guard evaluates against stale state; illegal transition persists Integration test with multi-entity flush
Concurrency / lost update Two writers both pass the guard; last write wins Optimistic-lock version column; assert on conflict
Transaction rollback State changed, side-effect event already dispatched Emit domain events after commit, outbox pattern
Annotation drift Typo in docblock silently widens the graph Lint the state/transition matrix in CI

Ramp-up. A Laravel team will burn 1–3 days each on Symfony bundle conventions, Doctrine event lifecycle, and annotation-based metadata — knowledge that has no reuse elsewhere in the codebase. A native Eloquent implementation is learnable in hours by any mid-level Laravel developer and is reviewable in a pull request. That asymmetry, combined with zero dependents and an explicit deprecation, is the whole case: recommend rejecting the dependency and adopting only its model.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib