PHPackages                             philiprehberger/php-state-machine - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. philiprehberger/php-state-machine

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

philiprehberger/php-state-machine
=================================

Declarative state machine with guards, hooks, and transition history

v1.0.4(1mo ago)11MITPHPPHP ^8.2CI passing

Since Mar 15Pushed 1mo agoCompare

[ Source](https://github.com/philiprehberger/php-state-machine)[ Packagist](https://packagist.org/packages/philiprehberger/php-state-machine)[ Docs](https://github.com/philiprehberger/php-state-machine)[ RSS](/packages/philiprehberger-php-state-machine/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (3)Versions (6)Used By (0)

PHP State Machine
=================

[](#php-state-machine)

[![Tests](https://github.com/philiprehberger/php-state-machine/actions/workflows/tests.yml/badge.svg)](https://github.com/philiprehberger/php-state-machine/actions/workflows/tests.yml)[![Latest Version on Packagist](https://camo.githubusercontent.com/3d70b0be479326e10783f9300a7c38f45e1052014397c6fe9392358a9be39e2c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7068696c69707265686265726765722f7068702d73746174652d6d616368696e652e737667)](https://packagist.org/packages/philiprehberger/php-state-machine)[![License](https://camo.githubusercontent.com/837ef39161d412e158f000f642708e16783dc7cdce920ed60c83b2508d4d3e2e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f7068696c69707265686265726765722f7068702d73746174652d6d616368696e65)](LICENSE)

Declarative state machine with guards, hooks, and transition history.

---

Requirements
------------

[](#requirements)

DependencyVersionPHP^8.2---

Installation
------------

[](#installation)

```
composer require philiprehberger/php-state-machine
```

---

Usage
-----

[](#usage)

### Define a state machine

[](#define-a-state-machine)

```
use PhilipRehberger\StateMachine\StateMachine;

$sm = StateMachine::define()
    ->states(['pending', 'processing', 'shipped', 'delivered', 'cancelled'])
    ->initial('pending')
    ->stateProperty('state')
    ->transition('process', 'pending', 'processing')
    ->transition('ship', 'processing', 'shipped')
    ->transition('deliver', 'shipped', 'delivered')
    ->transition('cancel', ['pending', 'processing'], 'cancelled')
    ->build();
```

### Apply transitions

[](#apply-transitions)

```
$order = new Order(); // $order->state === 'pending'

$result = $sm->apply($order, 'process');
// $order->state === 'processing'
// $result->from === 'pending'
// $result->to === 'processing'
```

### Check if a transition is allowed

[](#check-if-a-transition-is-allowed)

```
$sm->can($order, 'ship');    // true
$sm->can($order, 'deliver'); // false
```

### Get allowed transitions

[](#get-allowed-transitions)

```
$sm->allowedTransitions($order); // ['ship', 'cancel']
```

### Guards

[](#guards)

Guards are callables that must return `true` for the transition to proceed:

```
$sm = StateMachine::define()
    ->states(['pending', 'processing', 'shipped'])
    ->initial('pending')
    ->transition('process', 'pending', 'processing')
        ->guard(fn (object $order) => $order->isPaid)
    ->transition('ship', 'processing', 'shipped')
    ->build();
```

### Before and after hooks

[](#before-and-after-hooks)

```
$sm = StateMachine::define()
    ->states(['pending', 'processing'])
    ->initial('pending')
    ->transition('process', 'pending', 'processing')
        ->before(fn (object $order) => $order->log[] = 'Processing started')
        ->after(fn (object $order) => $order->log[] = 'Processing complete')
    ->build();
```

### Transition history

[](#transition-history)

```
$sm->apply($order, 'process');
$sm->apply($order, 'ship');

$history = $sm->history();
$history->all();  // [TransitionResult, TransitionResult]
$history->last(); // TransitionResult { transition: 'ship', from: 'processing', to: 'shipped' }
```

---

API
---

[](#api)

MethodDescription`StateMachine::define()`Create a new `StateMachineBuilder``$sm->apply(object $entity, string $transition)`Apply a transition, returns `TransitionResult``$sm->can(object $entity, string $transition)`Check if a transition is allowed`$sm->allowedTransitions(object $entity)`Get names of all allowed transitions`$sm->currentState(object $entity)`Get the entity's current state`$sm->history()`Get the `TransitionHistory` instance`$sm->initialState()`Get the defined initial state`$sm->states()`Get all defined states### StateMachineBuilder

[](#statemachinebuilder)

MethodDescription`->states(array $states)`Define valid states`->initial(string $state)`Set the initial state`->stateProperty(string $property)`Set the entity property name (default: `'state'`)`->transition(string $name, string|array $from, string $to)`Define a transition`->build()`Build the `StateMachine`### TransitionBuilder

[](#transitionbuilder)

MethodDescription`->guard(callable $guard)`Add a guard (must return `true` to allow)`->before(callable $hook)`Add a before-transition hook`->after(callable $hook)`Add an after-transition hook---

Development
-----------

[](#development)

```
composer install
vendor/bin/phpunit
vendor/bin/pint --test
vendor/bin/phpstan analyse
```

License
-------

[](#license)

MIT

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance90

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

5

Last Release

50d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/cfd7d24cbbf32400fa13ce0bbe7a31edd2d66a6d4488eafdb3d64c5337bf0435?d=identicon)[philiprehberger](/maintainers/philiprehberger)

---

Top Contributors

[![philiprehberger](https://avatars.githubusercontent.com/u/8218077?v=4)](https://github.com/philiprehberger "philiprehberger (6 commits)")

---

Tags

workflowhooksfsmstate-machinetransitionsguards

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/philiprehberger-php-state-machine/health.svg)

```
[![Health](https://phpackages.com/badges/philiprehberger-php-state-machine/health.svg)](https://phpackages.com/packages/philiprehberger-php-state-machine)
```

###  Alternatives

[pwm/s-flow

A lightweight library for defining state machines

742.5k](/packages/pwm-s-flow)[shrink0r/workflux

Finite state machine for php.

375.6k1](/packages/shrink0r-workflux)[tarfin-labs/event-machine

Event-driven state machines for Laravel with event sourcing, type-safe context, and full audit trail.

188.5k](/packages/tarfin-labs-event-machine)[ringierimu/state-workflow

Laravel State Workflow provide tools for defining and managing workflows and activities with ease.

3251.1k](/packages/ringierimu-state-workflow)[phpmentors/stagehand-fsm

A finite state machine

361.1k](/packages/phpmentors-stagehand-fsm)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
