PHP code example of definitely246 / state-machine

1. Go to this page and download the library: Download definitely246/state-machine library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

definitely246 / state-machine example snippets


namespace Light\Stuff;

/**
 * Handle flipSwitch event when light state is on
 */
class LightOn
{
	public function __construct(\StateMachine\Context $context)
	{
		$this->context = $context;
	}

	public function flipSwitch()
	{
		$this->context->setState(new LightOff($this->context));
		$this->context->set('status', 'off');
		return 'light is off';
	}
}

/**
 * Handle flipSwitch event when light state is off
 */
class LightOff
{
	public function __construct(\StateMachine\Context $context)
	{
		$this->context = $context;
	}

	public function flipSwitch()
	{
		$this->context->setState('LightOn');
		$this->context->status = 'on';
		return 'light is on';
	}
}

/**
 * This holds a context object and uses __call() to call our flipSwitch event
 */
class Light
{
	use \StateMachine\Stateful;

	protected $context = 'StateMachine\DefaultContext';

	protected $state = 'LightOn';

	public function status()
	{
		return $this->context->status;
	}
}


$light = new Light;		// no state yet
$light->status
$light->flipSwitch();	// 'light is off'
$light-flipSwitch();	// 'light is on'
$light->status();	// 'on'
$light->foobar();		// ERROR! there is no `foobar` method on Light

class Event1ChangedState1ToState2
{
	public function allow($context)
	{
		return true;
	}

	public function handle($context)
	{
		if (!$context->statesChanged) $context->statesChanged = 0;
		print "state1 -> state2\n";
		return $context->statesChanged++;
	}
}

class Event1ChangedState2ToState1
{
	public function allow($context)
   	{
   		return true;
   	}

   	public function handle($context)
   	{
		print "state2 -> state1\n";
   		return $context->statesChanged++;
   	}
}

$transitions = [
	[ 'event' => 'event1', 'from' => 'state1', 'to' => 'state2', 'start' => true],
	[ 'event' => 'event1', 'from' => 'state2', 'to' => 'state1' ],
];

$fsm = new StateMachine\FSM($transitions);

print $fsm->state() . PHP_EOL; // 'state1'

$fsm->event1();	// returns 1, prints 'state1 -> state2'

print $fsm->state() . PHP_EOL; // 'state2'

$fsm->event1();	// 2, prints 'state2 -> state1'

print $fsm->state() . PHP_EOL; // 'state1'

$transitions = [
	[
		'event' => 'insert',		// inserting money
		'from' 	=> 'idle',			// changes idle state
		'to' 	=> 'has money',		// to has money state
		'start' => true,			// this is starting state
	],
	[
		'event' => 'insert',		// inserting more
		'from' 	=> 'has money',		// money is okay
		'to'   	=> 'has money',		// state does not change
	],
	[
		'event' => 'refund',		// refunding when in
		'from' 	=> 'has money',		// has money state
		'to' 	=> 'idle',			// sets us back to idle
	],
	[
		'event' => 'purchase',		// stops the fsm because
		'from'	=> 'has money',		// all items have been
		'to'	=> 'out of stock',	// purchased and there is
		'stop'  => true,			// no more idle state
	],
	[
    	'event' => 'purchase',		// when we make it to this
	    'from' 	=> 'has money',		// transition, we purchase item.
	    'to' 	=> 'idle',			// order matters, see transition above?
	],
];

$machine = new StateMachine\FSM($transitions);

// throws StateMachine\Exceptions\TransitionHandlerNotFound

class InsertChangesIdleToHasMoney
{
	public function allow($context)
	{
		return true;	// allow this state change
	}

	public function handle($context)
	{
		// do moose stuff here
	}
}

$myCoolerContextObj = new MyCoolerContextObject;
$machine = new StateMachine\FSM($transitions, $myCoolerContextObj);

class MyModel extends \Eloquent
{
	protected $transitions = [
		...
	];

	public function __construct($attributes = array())
	{
		$this->fsm = new \StateMachine\FSM($this->transitions, $this);
	}
}

public function __construct($transitions, $context = null, $factory = '')
{
	$this->whiny = true;
	$this->stopped = false;
	$this->context = $context ?: new Context;
	$this->factory = is_string($factory) ? new ObjectFactory($factory, true) : $factory;
	$this->transitions = is_array($transitions) ? new Transitions($transitions) : $transitions;
	$this->state = $this->transitions->startingState();
	$this->addTransitionHandlers();
}

$context = array();
$machine = new StateMachine\FSM($transitions, $context, '\MyNamespaceToTransitionHandlerEvents');
// throws StateMachine\Exceptions\TransitionHandlerNotFound for \MyNamespaceToTranstitionHandlerEvents\InsertChangesIdleToHasMoney

$fsm->whiny = false;
$fsm->state() 		// 'state1'
$fsm->canPurchase(); 	// returns false
$fsm->purchase();	// returns false (does not throw CannotTransitionForEvent exception)

class InsertChangesIdleToHasMoney
{
	public function allow($context)
	{
		return true;	// allows this transition to run
	}

	public function handle($context)
	{
		$response = ['some' => 'stuff here'];
		throw new StateMachine\Exceptions\ShouldNotTransition($response);
	}
}

$fsm->state();	// 'idle'
$fsm->event3();	// ['some' => 'stuff here']
$fsm->state();	// 'idle' <-- not changed to 'has money' state

class InsertChangesHasMoneyToHasMoney
{
	public function allow($context, $coins)
	{
		return true;	// allows this transition to run
	}

	public function handle($context, $coins)
	{
		// force the vending machine to refund money...
		// this ends up calling $fsm->trigger('refund', []);
		if ($coins < 25) {
			throw new StateMachine\Exceptions\TriggerTransitionEvent('refund', $args = []);
		}
	}
}

$fsm->state();	// 'has money'
$fsm->insert(5);
$fsm->state();	// 'idle' <-- the user was refunded

$fsm->state();				// 'has money' state
$fsm->trigger('purchase', ['Pepsi']);	// user bought a pepsi
$fsm->state();				// 'out of stock' state
$fsm->isStopped();			// true
$fsm->insert(125);			// throws StateMachine\StateMachineIsStopped exception