christhompsontldr/laravel-fsm
Robust finite state machine for Laravel with zero-config setup. Define states and transitions with guards, actions, and entry/exit callbacks. Event-driven with comprehensive transition logging, validation, caching, and support for multiple state machines per model column.
FsmBuilder) decouples state logic from models, adhering to clean architecture principles. Guards, actions, and callbacks are modular, enabling maintainable business rules.approval_status and publication_status for a Document), making it adaptable to domain-specific needs.status column, transactional writes). Minimal changes required to adopt.HasFsm trait is lightweight and non-intrusive, requiring only:
dryRun) but doesn’t enforce testing strategies.draft → published) or branching (e.g., review → approved/rejected)? The package handles both but may need custom guards for complex logic.pay simultaneously)? The package uses transactions but may need application-level locks for critical paths.HasFsm trait integrates with Eloquent lifecycle hooks.StateTransitioned, TransitionFailed events integrate with Laravel’s event system.queuedAction) leverage Laravel Queues.dryRun for assertions).if-else checks, custom services).Document for approvals).dryRun before enabling transitions.if ($order->status === 'paid') → $order->fsm()->is(OrderStatus::Paid)).$order->status → $order->getFsmState()).trigger() or transitionFsm().Fsm namespace.php artisan vendor:publish --tag=fsm-config).OrderStatus).FsmDefinition classes in app/Fsm/Definitions.use HasFsm to target models.status).dryRun.php artisan fsm:cache:clear).TransitionFailed events in production.FsmDefinition), reducing duplication.TransitionFailed events for guard/action failures.php artisan fsm:diagram), which is invaluable for visualizing workflows.trigger()) scale naturally with Laravel’s queue system.selectForUpdate() in guards to prevent race conditions.event_logging.queue config to use a high-performance queue (e.g., Redis).| Failure Scenario | Impact | Mitigation |
|---|---|---|
| Invalid state transition | Data corruption or logic errors | Use can() checks before trigger(). Enable logging.log_failures. |
| Guard/action throws exception | Transition fails silently | Listen to TransitionFailed events; implement retry logic for idempotent actions. |
| Database transaction rollback | Partial state changes | Ensure all side effects (e.g., email sends) are idempotent or use queues. |
| Concurrent transitions | Race conditions (e.g., double payment) | Use database locks or optimistic concurrency control (e.g., version columns). |
| Package update breaks compatibility | Workflow failures | Test against package updates in staging. Use feature flags for major changes. |
| Logging overhead | Performance degradation | Disable logging in production if |
How can I help you explore Laravel packages today?