Skip to content

✨ A lightweight state machine library for PHP (inspired by xstate.js)

License

Notifications You must be signed in to change notification settings

mouadziani/xstate

Repository files navigation

xstate php logo

XState - State Machine for PHP

XState is a state machine library to play with any complex behavior of your PHP objects (inspired by xstate.js)

Installation

The recommended way to install Xstate is through Composer

composer require mouadziani/xstate

Define state machine workflow

Video state machine diagram

Let's say we want to define a state machine workflow for a video object, generally a video may have 3 states (playing, stopped, paused),

as a first step you have to create a new object from StateMachine class

use \Mouadziani\XState\StateMachine;

$video = StateMachine::make();

Then you have to define the allowed states as well as the default state

$video
    ->defaultState('stopped')
    ->states(['playing', 'stopped', 'paused']);

And finally the transitions

use \Mouadziani\XState\Transition;

$video->transitions([
    new Transition('PLAY', ['stopped', 'paused'], 'playing'),
    new Transition('STOP', 'playing', 'stopped'),
    new Transition('PAUSE', 'playing', 'paused'),
    new Transition('RESUME', 'paused', 'playing'),
]);

The Transition class expect 3 required params:

  • Trigger: As a name of the transition which will be used to trigger a specific transition (should be unique)
  • From: Expect a string for a single / or array for multiple initial allowed states
  • To: Expect string which is the next target state (should match one of the defined allowed states)

Guards (optional)

You can either define a guard callback for a specific transition using guard method, which must return a bool. If a guard returns false, the transition cannot be performed.

use \Mouadziani\XState\Transition;

$video->transitions([
    (new Transition('PLAY', ['stopped', 'paused'], 'playing'))
        ->guard(function ($from, $to) {
            return true;
        })
]);

💡 You can define the whole workflow using a single statement:

$video = StateMachine::make()
    ->defaultState('playing')
    ->states(['playing', 'stopped', 'paused'])
    ->transitions([
        new Transition('PLAY', ['stopped', 'paused'], 'playing'),
        new Transition('STOP', 'playing', 'stopped'),
        new Transition('PAUSE', 'playing', 'paused'),
    ]);

Work with states & transitions

Trigger transition

There are two ways to trigger a specific defined transition

1- Using transitionTo method and specify the name of the transition as an argument

$video->transitionTo('PLAY');

2- Or just calling the name of the transition from your machine object as a method

$video->play();

Occasionally triggering a transition may throw an exception if the target transition is not defined /or not allowed:

use \Mouadziani\XState\Exceptions;

try {
    $video->transitionTo('RESUME');
} catch (Exceptions\TransitionNotDefinedException $ex) {
    // the target transition is not defined
} catch (Exceptions\TransitionNotAllowedException $ex) {
    // the target transition is not allowed
}

Get the current state

echo $video->currentState(); // playing

Get the allowed transitions

$video->allowedTransitions(); // ['STOP', 'PAUSE']

Adding in-demand transition

$video->addTransition(new Transition('TURN_OFF', 'playing', 'stopped'));

Upcoming features

  • Add the ability to define guard for a specific transition
  • Define/handle hooks before/after triggering transition

Testing

composer test

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.

featured_repository