PHPackages                             rokde/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. rokde/state-machine

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

rokde/state-machine
===================

A generic state machine implementation

1.0.0(8mo ago)00[4 PRs](https://github.com/rokde/state-machine/pulls)MITPHPPHP ^8.4.0CI passing

Since Sep 5Pushed 3mo agoCompare

[ Source](https://github.com/rokde/state-machine)[ Packagist](https://packagist.org/packages/rokde/state-machine)[ Fund](https://www.buymeacoffee.com/robertkummer)[ Fund](https://www.paypal.me/rok)[ RSS](/packages/rokde-state-machine/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (7)Versions (6)Used By (0)

State Machine
=============

[](#state-machine)

 [![GitHub Workflow Status (master)](https://github.com/rokde/state-machine/actions/workflows/tests.yml/badge.svg)](https://github.com/rokde/state-machine/actions) [![Total Downloads](https://camo.githubusercontent.com/1ec0d639988e71457b5123832bd1cd8552eb7ff453ae381b33818a46816fb69b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f726f6b64652f73746174652d6d616368696e65)](https://packagist.org/packages/rokde/state-machine) [![Latest Version](https://camo.githubusercontent.com/ed691f7e7e13c83f9ae4f6e496f9393f3bbeb0b87c48d39c45dde73a71f00b61/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f726f6b64652f73746174652d6d616368696e65)](https://packagist.org/packages/rokde/state-machine) [![License](https://camo.githubusercontent.com/5f7c761e923da7c48b962e4b95314c32dc82a497b4a45191e6daf02734b63859/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f726f6b64652f73746174652d6d616368696e65)](https://packagist.org/packages/rokde/state-machine)

---

This package provides a generic implementation of the state machine pattern.

Real world examples
-------------------

[](#real-world-examples)

### Article Lifecycle

[](#article-lifecycle)

Rules / Business process of an article lifecycle:

- A draft article can be submitted to get reviewed: Draft --Submit-&gt; InReview
    - Guard: a draft article need to have all the required meta data
- The article in review can be approved so it will be scheduled for publication: InReview --Approve-&gt; Scheduled
    - Guard: the published\_at date has to be in the future or it gets published right away when it is null or in the past
- Scheduled articles gets published: Scheduled --Publish-&gt; Published
    - Guard: published\_at is now or in the past
- Updating draft articles or articles in review will get back into draft status : Draft/InReview --Update-&gt; Draft
    - Guard: current acting user has to be the author of the article
- Already published articles can be archived: Published --Archive-&gt; Archived
    - no guard

```
// ArticleState should be an Enum/BackedEnum or string constants
enum ArticleState {
    case Draft;
    case InReview;
    case Scheduled;
    case Published;
    case Archived;
}
// ArticleEvent should be an Enum/BackedEnum or string constants
enum ArticleEvent {
    case Submit;
    case Approve;
    case Publish;
    case Update;
    case Archive;
}

$article = new Article();// this is your context

$articleRegistry = new \Rokde\StateMachine\TransitionRegistry();
$articleRegistry->addTransition(
    ArticleState::Draft, ArticleEvent::Submit, ArticleState::InReview,
    guard: fn($article) => $article->hasRequiredMeta(),
)->addTransition(
    ArticleState::InReview, ArticleEvent::Approve, ArticleState::Scheduled,
    guard: fn($article) => $article->published_at > now(),
)->addTransition(
    ArticleState::Scheduled, ArticleEvent::Publish, ArticleState::Published,
    guard: fn($article) => $article->published_at === null || $article->published_at addTransition(
    ArticleState::Draft, ArticleEvent::Update, ArticleState::Draft,
    guard: fn($article) => $article->author_id === currentUserId(),
)->addTransition(
    ArticleState::InReview, ArticleEvent::Update, ArticleState::Draft,
    guard: fn($article) => $article->author_id === currentUserId(),
)->addTransition(
    ArticleState::Published, ArticleEvent::Archive, ArticleState::Archived,
);

$sm = new \Rokde\StateMachine\StateMachine($articleRegistry);
$nextStatus = $sm->apply($article->status, ArticleEvent::Submit, $article);
$article->status = $nextStatus;
$article->save();
```

If you want a diagram representation of your process workflow, then just transform the registry to mermaid:

```
$transformer = new Rokde\StateMachine\Transformers\RegistryMermaidTransformer();
$mermaidCode = $transformer->transform($articleRegistry);
```

This results in a diagramm like this:

 ```
stateDiagram-v2
  Draft --> InReview : Submit
  Draft --> Draft : Update
  InReview --> Scheduled : Approve
  InReview --> Draft : Update
  Scheduled --> Published : Publish
  Published --> Archived : Archive

```

      Loading The test can also be seen in [./tests/Feature/MermaidTest.php](MermaidTest.php).

### Order Lifecycle

[](#order-lifecycle)

This is built in the [./tests/Feature/TransitionTest.php](TransitionTest.php).

### Developer Happiness

[](#developer-happiness)

🧹 Keep a modern codebase with **Pint**:

```
composer lint
```

✅ Run refactors using **Rector**

```
composer refactor
```

⚗️ Run static analysis using **PHPStan**:

```
composer test:types
```

✅ Run unit tests using **PEST**

```
composer test:unit
```

🚀 Run the entire test suite:

```
composer test
```

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance71

Regular maintenance activity

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 95.5% 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

Unknown

Total

1

Last Release

252d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/4946056?v=4)[Robert Kummer](/maintainers/rokde)[@rokde](https://github.com/rokde)

---

Top Contributors

[![rokde](https://avatars.githubusercontent.com/u/4946056?v=4)](https://github.com/rokde "rokde (21 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

phpstate-machine

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[imanghafoori/laravel-anypass

A minimal yet powerful package to help you in development.

21421.6k](/packages/imanghafoori-laravel-anypass)

PHPackages © 2026

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