A simple finite state machine with minimal dependencies

0.0.4 2013-09-24 15:09 UTC


This is a simple, no-deps PHP state machine.


Update your composer.json file adding the following dependency and run php composer.phar update carlescliment/state-machine:

    "carlescliment/state-machine": "0.0.4"


Implementing a state machine is straight-forward. You need four components; a statable object, states, transitions and the state machine.


use carlescliment\StateMachine\Model\Statable,

class SemaphoreStates
    const OPEN = '';
    const WARNING = 'semaphore.warning';
    const LOCKED = 'semaphore.locked';

    public static function all()
        return array(self::OPEN, self::WARNING, self::LOCKED);

class SemaphoreTransitions
    const GIVE_PASS = 'semaphore.give_pass';
    const WARN = 'semaphore.warn';
    const LOCK = 'semaphore.lock';

class Semaphore implements Statable
    private $state = SemaphoreStates::LOCKED;

    public function getState()
        return $this->state;

    public function setState($state)
        $this->state = $state;
        return $this;

class SemaphoreStateMachine extends StateMachine
    public function __construct()

        foreach (SemaphoreStates::all() as $state) {

        $transitions = array(
            new Transition(AuctionTransitions::GIVE_PASS, AuctionStates::LOCKED, AuctionStates::OPEN),
            new Transition(AuctionTransitions::GIVE_PASS, AuctionStates::WARNING, AuctionStates::OPEN),
            new Transition(AuctionTransitions::WARN, AuctionStates::OPEN, AuctionStates::WARNING),
            new Transition(AuctionTransitions::WARN, AuctionStates::LOCKED, AuctionStates::WARNING),
            new Transition(AuctionTransitions::LOCK, AuctionStates::OPEN, AuctionStates::LOCKED),
            new Transition(AuctionTransitions::LOCK, AuctionStates::WARNING, AuctionStates::LOCKED),
        foreach ($transitions as $transition) {

Now, you can operate with your state machine:


$semaphore = new Semaphore;

$machine = new SemaphoreStateMachine;
$machine->execute(SemaphoreTransitions::GIVE_PASS, $semaphore);
$machine->execute(SemaphoreTransitions::WARN, $semaphore);
$machine->execute(SemaphoreTransitions::LOCK, $semaphore);