Skip to content

A PHP Finite State Machine (with Laravel 5.4 integration)

License

Notifications You must be signed in to change notification settings

studio-net/OverStated

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

86 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A PHP Finite State Machine for Laravel 5.4+

Originaly based on https://github.com/daveawb/understated

Why use an FSM?

FSM's are a resource that allow developers tight control over resources within an application. There are many articles detailing FSM's and what they are and what they're capable of so I won't go into much detail here.

Requirements

  • >= PHP 7.0
  • >= Laravel 5.4

Installation

Composer

Add the following to your composer.json file

{
    "require": {
        "studionet/overstated": "0.1.0"
    }
}

Laravel Integration

Open config/app.php and register the required service provider.

'providers' => [
    // ...
    OverStated\Providers\OverStatedServiceProvider::class,
]

A Simple FSM

First you have to define states as classes, for example :

use OverStated\States\State;

/**
 * Class Deleted
 */
class Deleted extends State {
	/** @var string $id */
	protected $id = 'deleted';
}

And transitions :

use OverStated\Transitions\Transition;

/**
 * Class Delete
 */
class Delete extends Transition {
	// Transition slug
	public $slug = "delete";
	// Transition nice name
	public $name = "Delete";
	// Transition description
	public $description = "Delete a property";
	// Transition from which state(s) you can transit
	public $from = ["draft", "valid"];
	// Transition destination state
	public $to = "deleted";
}

The simple way to use it is in a Model, with the Stateful trait

use OverStated\Support\Stateful;
use App\Fsm\Property\States;
use App\Fsm\Property\Transitions;

class Post extends Model {
	use Stateful;

	/** @type array $attributes default values */
	protected $attributes = [
		'status' => "draft",
	];

	// You have to define fields which will be controlled by FSMs
	// Here, it's the field 'status', which have states and a transition

	/** @var array $fsmDefinitions */
	protected $fsmDefinitions = [
		'status' => [
			'states' => [
				States\Draft::class,
				States\Valid::class,
				States\Deleted::class,
			],
			'transitions' => [
				Transitions\Delete::class,
			]
		]
	];
}

After that, you can update defined field like :

// Will echo "draft"
echo $post->status;

// Change status
$post->fsmTransit("status", "delete");

// Will echo "deleted"
echo $post->status;

// Will throw an OverStated\Exceptions\TransitionException
$post->fsmTransit("status", "delete");

Or, you can manually create FSM

use OverStated\Builders\GraphBuilder;
use App\Fsm\Property\States;
use App\Fsm\Property\Transitions;

$builder = new GraphBuilder();
$builder = $builder->create();

// Set states
$builder->state(States\Draft::class);
$builder->state(States\Valid::class);
$builder->state(States\Deleted::class);

// Set transitions
$builder->transition(Transitions\Delete::class);

// Get the machine from the builder
$fsm = $builder->getMachine();

// Initialise state
$fsm->initialise("draft");

You can now use it

// Will output "draft"
$fsm->getState()->getId();

// Change state
$fsm->transition("delete");

// Will output "deleted"
$fsm->getState()->getId();

// Will throw an OverStated\Exceptions\TransitionException
$fsm->transition("delete");

Validation

You can add a hook on a transition by overriding validatesTransition().

use OverStated\Transitions\Transition;

/**
 * Class Validate
 */
class Validate extends Transition {
	public $slug = "validate";
	public $name = "Validate";
	public $description = "Validate a post";
	public $from = ["draft"];
	public $to = "valid";

	/**
	 * @override
	 */
	public function validatesTransition() {
		// Model is available if you use Stateful trait on a Model
		$post = $this->machine->getModel();
		if (empty($post->content)) {
			$this->addError('Content must be set')
		}
	}

}

About

A PHP Finite State Machine (with Laravel 5.4 integration)

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • PHP 100.0%