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

Laravel State Machine Laravel Package

iotron/laravel-state-machine

A Laravel package for building state machines around Eloquent models. Define states and allowed transitions, guard status changes, and keep workflow logic organized, explicit, and easy to test. Helps replace scattered status checks with a clear, maintainable transition map.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package implements the state machine pattern directly on Eloquent models — transitions, guards/hooks, enum-backed states, and transition history. That maps cleanly onto the lifecycle-heavy domain objects most Laravel applications already have (orders, subscriptions, approvals, onboarding). It is a single-purpose library with a narrow surface area, which keeps architectural coupling low: the state machine lives inside the model layer rather than introducing a new service tier or event bus. The v1.0.1 release does not change this shape; it hardens the transition path and widens framework support.

Integration feasibility. Composer-installable with a clearly stated support matrix (Laravel 11/12/13, PHP 8.2–8.4, MySQL/PostgreSQL/SQLite). The package self-describes as a drop-in replacement for asantibanez/laravel-eloquent-state-machines, which materially lowers adoption cost for teams already using that package — the swap is a dependency change plus a namespace/API parity check rather than a re-architecture. New adopters get a conventional, well-understood pattern. The main integration work is publishing and owning the transition-history schema and deciding where transaction boundaries live in application code.

Technical risk. The headline risk in 1.0.1 is that the transaction change is behavioral, not merely additive. StateMachine now inspects DB::transactionLevel() and reuses an ambient transaction instead of opening a nested one. That is the right default for most applications, but it changes rollback semantics: a transition that previously failed in isolation and rolled back to a savepoint will now roll back the caller's entire transaction. Any workflow relying on partial-commit or per-transition isolation must be re-validated. Secondary risks: a fork-based lineage means parity drift with upstream, and the Laravel 13 lane drops PHP 8.2, so the support matrix is not uniform across framework versions.

Key questions.

  • Who maintains the package, under what license, and what is the release cadence and bus factor?
  • Is there a documented API-parity guarantee with the upstream asantibanez package, and how are divergences tracked?
  • Is 1.0.1 intended as a non-breaking patch relative to 1.0.0, given the transaction-semantics change?
  • How is transition history stored, indexed, and pruned — is there a published migration and retention story?
  • What is the recommended concurrency model for transitions on the same model instance (row locking, optimistic versioning, queue serialization)?
  • Are hooks/guards executed inside or outside the transaction boundary, and are side effects expected to be idempotent?

Integration Approach

Stack fit. Native to Laravel: Eloquent models, DB facade transaction handling, enum support, and the framework's testing conventions. No non-standard runtime dependencies are implied beyond Laravel itself and Carbon. It slots into an existing Laravel codebase without new infrastructure, and the supported database set covers typical local (SQLite) and production (MySQL/PostgreSQL) configurations.

Migration path. Two distinct paths:

  1. From the upstream asantibanez package — swap the composer requirement, verify namespace and method parity against the in-house model definitions, and run the full existing state machine test suite before merging. Treat this as a dependency substitution with a parity gate, not a refactor.
  2. Greenfield — install, publish/author the history migration, define states as a backed enum, attach the trait and transition map to one pilot model, then expand.

For both, the decisive step is auditing existing DB::transaction() call sites around transitions to confirm the new reuse behavior matches intent.

Compatibility. Pin the matrix explicitly in CI: Laravel 11/12 on PHP 8.2–8.4, Laravel 13 on PHP 8.3–8.4 (mirroring the upstream workflow's PHP 8.2 exclusion). Confirm that the application's own Laravel constraint and PHP floor align before bumping; a Laravel 13 upgrade and this package bump should travel together rather than sequentially. Verify behavior on the target production database, since savepoint handling is the specific thing that changed.

Sequencing.

  1. Land the dependency update behind the existing test suite; no behavior change expected for callers that never wrapped transitions in an outer transaction.
  2. Add a transaction-boundary test in the application's own suite mirroring the new TransactionBoundaryTest — assert both the ambient-transaction and no-transaction paths.
  3. Pilot on one non-critical model with history tracking enabled; observe write volume and table growth.
  4. Promote to order/payment-critical models only after rollback semantics are confirmed in staging on the production database engine.
  5. Update the Laravel 13 lane in CI last, once the package bump is settled.

Operational Impact

Maintenance. The codebase is small and the change surface per release is narrow, so ongoing maintenance is light. The real cost is lineage tracking: as a drop-in replacement for an actively used upstream package, the team inherits responsibility for monitoring upstream changes, Laravel release cycles, and any divergence in behavior. Assign a named owner for dependency bumps and budget a review per Laravel minor release.

Support. Support posture is the weakest-known dimension. Release notes indicate an active CI matrix and a meaningful test suite (TransactionBoundaryTest, expanded enum and history coverage), which is a positive signal for quality. But there is no stated commercial support, SLA, or security disclosure process. For business-critical workflows, plan on internal capability to read and patch the package rather than relying on upstream responsiveness.

Scaling. Two scaling axes matter. First, transition history: every transition writes a row, so high-volume models need an indexed history table and a retention/pruning policy defined up front — this is application-owned work. Second, concurrency: transitions on the same aggregate must be serialized (row locks or queued commands) to avoid interleaved state changes; the package's transaction handling makes this cleaner but does not by itself prevent races. The transaction-level check adds one cheap introspection call per transition — negligible.

Failure modes.

  • Rollback scope expansion — a failed transition inside a caller's transaction now rolls back the whole unit of work; callers must handle exceptions accordingly.
  • Savepoint-dependent logic — any code or database configuration relying on nested savepoints will behave differently.
  • Missing or mismatched state mapping — undefined transitions surfacing at runtime rather than at boot; mitigate with enum-typed states and tests.
  • History write failure — if history persistence fails inside the reused transaction, the state change rolls back with it; confirm this is the desired coupling.
  • Silent parity gaps — divergence from the upstream package could surface only when a developer assumes upstream behavior.

Ramp-up. Low. State machines are a familiar pattern and the package's API is idiomatic Laravel, so a mid-level developer can ship a first model in under a day. The learning investment belongs in the transaction semantics and history/retention design rather than the library API. Budget a short internal write-up documenting the transaction-boundary rule, since that is the one place where intuition from the previous version (or from hand-rolled transition code) will be wrong.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console