- How do I add state machine behavior to an Eloquent model in Laravel?
- Use the `HasStates` trait on your model and define a cast for the state field. For example, cast `state` to your custom state class like `PaymentState::class`. The package handles serialization and deserialization automatically.
- What Laravel and PHP versions does `spatie/laravel-model-states` support?
- The package requires **Laravel 8+** and **PHP 8+** for full features, including attributes for state configuration. PHP 7.4+ may work but lacks attribute support and some optimizations.
- Can I define custom state transitions with guards or conditions?
- Yes. Use the `allowTransition()` method in your state classes to define guards. For example, restrict transitions from `Pending` to `Paid` only if a payment succeeds by returning a boolean condition.
- How do I handle multiple state fields (e.g., `order_status` and `payment_status`) on a single model?
- The package supports multiple state fields by casting each field to its respective state class. For example, cast `order_status` to `OrderState::class` and `payment_status` to `PaymentState::class` in your model’s `$casts` array.
- Does this package work with Laravel events for state changes?
- Yes. The package dispatches a `StateChanged` event by default when a state transitions. You can listen to this event or create custom events in your state classes for side effects like notifications or auditing.
- How do I customize the database column storing the state (e.g., use `state` instead of a class name)?
- Use the static `$name` property in your state class to define a custom name. For example, `public static string $name = 'paid';` will store `'paid'` in the database instead of the class name.
- Is there a performance impact when using state objects in high-throughput systems?
- Serialization/deserialization of state objects adds minor overhead. For high-throughput systems, benchmark critical paths (e.g., bulk state transitions) and consider optimizing by caching state objects or using simpler casts if needed.
- How do I test state transitions and side effects in PHPUnit?
- Mock state objects in unit tests by creating fake state classes or using PHPUnit’s mock builder. Test transitions with `model->transitionTo(StateClass::class)` and verify side effects (e.g., events fired) using Laravel’s event testing helpers.
- Can I migrate existing models with ad-hoc state logic (e.g., integer enums) to this package?
- Yes, but refactoring is required. Replace enum columns with string columns for state names, update your model to use `HasStates`, and create corresponding state classes. Use a custom `StateResolver` if auto-discovery isn’t feasible.
- What alternatives exist for state machines in Laravel, and why choose this package?
- Alternatives include `verot/flux` (state machines) or `spatie/laravel-activitylog` (for auditing). This package stands out for its **clean OOP design**, **type safety**, and **seamless Eloquent integration**, making it ideal for domain-driven workflows where states have unique behaviors.