A simple state machine that allows transitioning model states based on pre-defined rules.
Installation
You can install the package via composer:
composer require jxckaroo/laravel-state-machine
Run the package migrations:
php artisan migrate
Usage
Add the Jxckaroo\StateMachine\Stateable
trait to your model(s) that require state management & define your states on your model(s):
States & Rules
Below is an example of a ready-to-go model.
use Illuminate\Database\Eloquent\Model;
use Jxckaroo\StateMachine\Stateable;
class Order extends Model
{
use Stateable;
protected array $states = [
'factory' => ExampleRule::class,
'complete' => [
ExampleRule::class,
ExampleRuleFalse::class
]
];
// ...
}
When defining your states, you can specify either one or many rules as above. Your rules must extend Jxckaroo\StateMachine\Contracts\StateRule
and must contain a validate
method as per the below example:
class ExampleRule extends StateRule
{
public function validate(Model $model): bool
{
return $model->getKey() !== null;
}
}
You can also add specific error messages when a validation fails, like so:
class ExampleRuleFailure extends StateRule
{
public function validate(Model $model): bool
{
if (!$model->isProductionReady()) {
$this->addError("Model is not ready for production.");
return false;
}
return true;
}
}
These error messages can then be retrieved by calling $model->stateErrors()
after attempting to transition state, resulting in a collection of errors returning, like below:
Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[0] => Array
(
[message] => Model is not ready for production.
[rule] => Jxckaroo\StateMachine\Rules\ExampleRuleFailure
)
)
[escapeWhenCastingToString:protected] =>
)
Model Interactions
// Get model
$order = Order::find(1);
// Get current state of a model
$order->state;
// Get the state history of a model
$order->stateHistory;
// Attempt to transition model to one of your defined states
$order->transitionToState("factory");
// Attempt to transition model to previous state as defined in $order->states
$order->transitionToPreviousState();
// Attempt to transition model to next state as defined in $order->states
$order->transitionToNextState();
// Get all available states on model
$order->states();
Check if a state transition is successful:
$order = Order::find(1);
if ($order->transitionToState("complete")->isSuccessful()) {
// Successful transition
} else {
// Get a collection of all rules that failed
$order->stateErrors();
}
Testing
composer test
Changelog
Please see CHANGELOG for more information what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security related issues, please email [email protected] instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.
Laravel Package Boilerplate
This package was generated using the Laravel Package Boilerplate.