2017 © Pedro Peláez
 

library finite

A simple PHP5.3+ Finite State Machine

image

yohang/finite

A simple PHP5.3+ Finite State Machine

  • Friday, February 16, 2018
  • by yohang
  • Repository
  • 70 Watchers
  • 1001 Stars
  • 872,706 Installations
  • PHP
  • 23 Dependents
  • 2 Suggesters
  • 144 Forks
  • 47 Open issues
  • 17 Versions
  • 7 % Grown

The README.md

Finite, A Simple PHP Finite State Machine

Finite is a Simple State Machine, written in PHP. It can manage any Stateful object by defining states and transitions between these states., (*1)

As of version 2, Finite is a low-deps and lightweight state machine library, thanks to the use of PHP Enums., (*2)

CI Status, (*3)

Disclaimer

I don't have the time anymore to maintain this lib. Here is the documentation for the brand new Finite V2, based on PHP >= 8.1 Enums, but don't expect it to be updated on a regular basis., (*4)

Features

  • Manage State/Transition graph for an object
  • Attach business logic to states
  • Listen to transitions between state to trigger your domain code
  • Symfony integration
  • Twig Extension

Getting started

Installation (via composer)

 $ composer req yohang/finite

Define your state enum

enum DocumentState: string implements State
{
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case REPORTED = 'reported';
    case DISABLED = 'disabled';

    public static function getTransitions(): array
    {
        return [
            new Transition('publish', [self::DRAFT], self::PUBLISHED),
            new Transition('clear', [self::REPORTED, self::DISABLED], self::PUBLISHED),
            new Transition('report', [self::PUBLISHED], self::REPORTED),
            new Transition('disable', [self::REPORTED, self::PUBLISHED], self::DISABLED),
        ];
    }
}

Define your Stateful Object

Your stateful object just need to have a state property, (*5)

class Document
{
    private DocumentState $state = DocumentState::DRAFT;

    public function getState(): DocumentState
    {
        return $this->state;
    }

    public function setState(DocumentState $state): void
    {
        $this->state = $state;
    }
}

Initializing a simple StateMachine

use Finite\StateMachine;

$document = new Document;

$sm = new StateMachine;

// Can we process a transition ?
$sm->can($document, 'publish');

// Apply a transition
$sm->apply($document, 'publish'); 

Add business logic to states

Finite < 2.0 had properties on states. A metadata mechanism that allowed to add business properties on states to define the behavior of on object, depending on its state., (*6)

The idea behind this was to avoid to test the state in your domain code (A controller must not throw a 404 if the state is draft. But it can throw a 404 if the current state does not have a "visible" property. That was the idea)., (*7)

Finite 2 does not needs this. PHP Enums can have methods. So, replace your properties with simple methods on your state., (*8)

enum DocumentState: string implements State
{
    // ...

    public function isDeletable(): bool
    {
        return in_array($this, [self::DRAFT, self::DISABLED]);
    }

    public function isPrintable(): bool
    {
        return in_array($this, [self::PUBLISHED, self::REPORTED]);
    }
}

After that, you can use theses methods on your object, even without instantiating the state machine., (*9)

var_dump($document->getState()->isDeletable());
var_dump($document->getState()->isPrintable());

The Versions

01/12 2015