jooservices / state-machine
A PHP 8.5+ configuration-driven finite state machine for any PHP object
Requires
- php: >=8.5
- psr/event-dispatcher: ^1.0
Requires (Dev)
- captainhook/captainhook: ^5.23
- captainhook/plugin-composer: ^5.3
- fakerphp/faker: ^1.24
- friendsofphp/php-cs-fixer: ^3.65
- laravel/pint: ^1.18
- phpbench/phpbench: ^1.6
- phpmd/phpmd: ^2.15
- phpstan/phpstan: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^12.0 || ^13.0
- squizlabs/php_codesniffer: ^3.8 || ^4.0
This package is auto-updated.
Last update: 2026-07-22 02:29:59 UTC
README
The JOOservices State Machine is a PHP 8.5+ configuration-driven finite state machine for any PHP object — DTOs, POPOs, or framework models. Zero framework coupling. State is a string property on the subject.
Package name: jooservices/state-machine
Latest stable release: v1.0.0
Install
composer require jooservices/state-machine
Quick example
use JOOservices\StateMachine\StateMachineFactory; final class Order { public function __construct( public string $status = 'pending', ) {} } $config = [ 'property' => 'status', 'states' => ['pending', 'confirmed', 'shipped', 'cancelled'], 'initial_state' => 'pending', 'transitions' => [ 'confirm' => ['from' => ['pending'], 'to' => 'confirmed'], 'ship' => ['from' => ['confirmed'], 'to' => 'shipped'], 'cancel' => ['from' => ['pending', 'confirmed'], 'to' => 'cancelled'], ], ]; $order = new Order(); $machine = (new StateMachineFactory())->create($order, 'order', $config); if ($machine->can('confirm')) { $machine->apply('confirm'); } echo $machine->getState(); // confirmed
What is supported today
- configuration-driven graphs validated at construction time
can()/apply()/getAvailableTransitions()- pluggable state accessors (property reflection or getter/setter)
- guards and before/after callbacks as class strings
- optional PSR-14 lifecycle events
- multiple independent graphs per subject (separate machine instances)
- pure PHP 8.5+ with no Laravel/Symfony runtime requirement
Important current limitations
- guards and callbacks are constructed with
new $class()(no container resolution) - event dispatcher is optional; consumers bring their own PSR-14 implementation
- no built-in persistence, Eloquent casts, or service providers
- missing properties/methods are handled conservatively by accessors (null / no-op)
Documentation
Start with:
- Documentation Hub
- Changelog
- AI Skills Usage Guide
- phpDocumentor config:
phpdoc.dist.xml - Installation
- Quick Start
- Risks, Legacy, and Gaps
AI Support
This repository includes an AI skill pack for agents working in Cursor, Claude Code, VS Code, JetBrains, and Antigravity.
Start with:
The canonical skill source lives in .github/skills/, with adapter layers for each supported AI environment.
Development
composer lint
composer lint:all
composer test
composer test:coverage
composer check
composer ci
Contributor workflow details live in:
Approved Git flow summary:
- normal feature and fix work branches from
developand PRs back intodevelop - release preparation uses
release/<version>fromdevelop, then PRs intomaster - releases are tagged from
master mastermerges back intodevelopafter release or hotfix completion
Community
GitHub Actions and Services
Current GitHub Actions coverage:
CI: security checks, linting, tests, 95% minimum statement coverage, coverage upload, and optional SonarQube Cloud analysis whenSONAR_TOKENis configuredRelease: validate tags, create GitHub releases, trigger Packagist updatePR Labeler: apply labels to pull requestsSemantic PR Title: enforce pull request title formatOpenSSF Scorecard: publish scorecard results as SARIFSecret Scanning: workflow file exists, but thegitleaksjob may be disabled depending on repository settings
External services currently used by workflows:
Codecovfor coverage upload inci.ymlPackagistupdate webhook inrelease.ymlGitHub ReleasesandGitHub Discussionsinrelease.ymlOpenSSF Scorecardinscorecard.yml
License
This project is licensed under the MIT License.