Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP state machine framework

Tags:

I doubt that is there any state machine framework like https://github.com/pluginaweek/state_machine for PHP.

I've had to define many if-else logical clauses, and I would like something to help make it more fun by just defining:

  1. Condition required to transition
  2. State after transition

Then this can be reused to check if conditions match or not, for example

$customer->transition('platinum');

I expect this line of code to implicitly check if the customer can transition or not. Or explicitly check by:

$customer->canTransitTo('platinum');

Thanks in advance, noomz

like image 523
noomz Avatar asked Nov 25 '10 05:11

noomz


2 Answers

I don't know a framework like this (which doesn't mean it does not exist). But while not as feature packed as the linked framework, the State pattern is rather simple to implement. Consider this naive implementation below:

interface EngineState
{
    public function startEngine();
    public function moveForward();
}

class EngineTurnedOffState implements EngineState
{
    public function startEngine()
    {
        echo "Started Engine\n";
        return new EngineTurnedOnState;
    }
    public function moveForward()
    {
        throw new LogicException('Have to start engine first');
    }
}

class EngineTurnedOnState implements EngineState
{
    public function startEngine()
    {
        throw new LogicException('Engine already started');
    }
    public function moveForward()
    {
        echo "Moved Car forward";
        return $this;
    }
}

After you defined the states, you just have to apply them to your main object:

class Car implements EngineState
{
    protected $state;
    public function __construct()
    {
        $this->state = new EngineTurnedOffState;
    }
    public function startEngine()
    {
        $this->state = $this->state->startEngine();
    }
    public function moveForward()
    {
        $this->state = $this->state->moveForward();
    }
}

And then you can do

$car = new Car;
try {
    $car->moveForward(); // throws Exception
} catch(LogicException $e) {
    echo $e->getMessage();
}

$car = new Car;
$car->startEngine();
$car->moveForward();

For reducing overly large if/else statements, this should be sufficient. Note that returning a new state instance on each transition is somewhat inefficient. Like I said, it's a naive implementation to illustrate the point.

like image 175
Gordon Avatar answered Oct 12 '22 17:10

Gordon


FSM Package and FSM Parser.

like image 29
Elzo Valugi Avatar answered Oct 12 '22 19:10

Elzo Valugi