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

ActiveSymfony-bundle[Utility &amp; Helpers](/categories/utility)

samuel4x4/state-machine-bundle
==============================

Bundle for the very lightweight yet powerful PHP state machine

v0.6.5(2mo ago)0183MITPHPPHP ^7.4|^8.0|^8.1

Since May 26Pushed 2mo agoCompare

[ Source](https://github.com/samuel4x4/StateMachineBundle)[ Packagist](https://packagist.org/packages/samuel4x4/state-machine-bundle)[ RSS](/packages/samuel4x4-state-machine-bundle/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)Dependencies (3)Versions (26)Used By (0)

A very lightweight yet powerful PHP state machine bundle
========================================================

[](#a-very-lightweight-yet-powerful-php-state-machine-bundle)

Define your states, define your transitions and your callbacks: we do the rest. The era of hard-coded states is over!

[![Build](https://github.com/winzou/StateMachineBundle/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/winzou/StateMachineBundle/actions/workflows/build.yml)

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

[](#installation)

### Installation (via composer)

[](#installation-via-composer)

```
composer require winzou/state-machine-bundle
```

### Register the bundle

[](#register-the-bundle)

```
// app/AppKernel.php
public function registerBundles()
{
    return array(
        // ...
        new winzou\Bundle\StateMachineBundle\winzouStateMachineBundle(),
    );
}
```

Usage
-----

[](#usage)

### Configure a state machine graph

[](#configure-a-state-machine-graph)

In order to use the state machine of this bundle, you first need to define a graph. A graph is a definition of states, transitions and optionally callbacks ; all attached on an object from your domain. Multiple graphs can be attached to the same object.

Let's define a graph called *simple* for our `Article` object:

```
# app/config/config.yml

winzou_state_machine:
    my_bundle_article:
        class: My\Bundle\Entity\Article # class of your domain object
        property_path: state            # property of your object holding the actual state (default is "state")
        graph: simple                   # name of the graph (default is "default")
        # list of all possible states:
        states:
            - new
            - pending_review
            - awaiting_changes
            - accepted
            - published
            - rejected
        # list of all possible transitions:
        transitions:
            create:
                from: [new]
                to: pending_review
            ask_for_changes:
                from: [pending_review, accepted]
                to: awaiting_changes
            submit_changes:
                from: [awaiting_changes]
                to: pending_review
            approve:
                from: [pending_review, rejected]
                to: accepted
            publish:
                from: [accepted]
                to: published
        # list of all callbacks
        callbacks:
            # will be called when testing a transition
            guard:
                guard_on_submitting:
                    on:   'submit_changes'                        # call the callback on a specific transition
                    do:   ['@my.awesome.service', 'isSubmittable']  # will call the method of this Symfony service
                    args: ['object']                              # arguments for the callback
            # will be called before applying a transition
            before:
                update_reviewer:
                    on:   'create'
                    do:   ['@my.awesome.service', 'update']
                    args: ['object']
            # will be called after applying a transition
            after:
                email_on_publish:
                    on:   'publish'
                    do:   ['@my.awesome.service', 'sendEmail']
                    args: ['object', '"Email title"']
```

So, in the previous example, the object `Article` has 6 possible states, and those can be achieved by applying some transitions to the entity. For example, when creating a new `Article`, you would apply the 'create' transition to the entity, and after that the state of it would become *pending\_review*.

Let's imagine now that, after an exhaustive review, someone decides the `Article` was not good enough, so it would like to ask you for some changes. Therefore, they would apply the *ask\_for\_changes* transition, and now the state would be *awaiting\_changes*.

### Using the state machine

[](#using-the-state-machine)

#### Definitions

[](#definitions)

The state machine is the object actually manipulating your object. By using the state machine you can test if a transition can be applied, actually apply a transition, retrieve the current state, etc. *A state machine is specific to a couple object + graph.* It means that if you want to manipulate another object, or the same object with another graph, *you need another state machine*.

The factory helps you to get the state machine for these couples object + graph. You give an object and a graph name to it, and it will return you the state machine for this couple. The factory is a service named `SM\Factory\Factory`.

#### Usage

[](#usage-1)

```
public function myAwesomeAction($id, \SM\Factory\Factory $factory)
{
    // Get your domain object
    $article = $this->getRepository('MyAwesomeBundle:Article')->find($id);

    // Get the state machine for this object, and graph called "simple"
    $articleSM = $factory->get($article, 'simple');
}
```

Now, the `$articleSM` has a bunch of methods that will allow you to check if the desired transitions are possible, given the state of the object we have passed to it (`$article` in our case). For example, we can:

```
// Check if a transition can be applied: returns true or false
$articleSM->can('a_transition_name');

// Apply a transition
$articleSM->apply('a_transition_name');

// Get the actual state of the object
$articleSM->getState();

// Get all available transitions
$articleSM->getPossibleTransitions();
```

### Callbacks

[](#callbacks)

Callbacks are used to guard transitions or execute some code before or after applying transitions. This bundle adds the ability to use Symfony2 services in the callbacks.

###  Health Score

51

—

FairBetter than 96% of packages

Maintenance90

Actively maintained with recent releases

Popularity15

Limited adoption so far

Community17

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 50.6% 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 ~178 days

Recently: every ~187 days

Total

25

Last Release

81d ago

PHP version history (4 changes)v0.1PHP &gt;5.3.0

0.5.0PHP ^7.1.3

0.5.1PHP ^7.1.3|^8.0

v0.6.1PHP ^7.4|^8.0|^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/9eb39ec7050814cc24a6657a65e805b676abe8cfed7330f10f7c921093173215?d=identicon)[samuel4x4](/maintainers/samuel4x4)

---

Top Contributors

[![winzou](https://avatars.githubusercontent.com/u/702928?v=4)](https://github.com/winzou "winzou (40 commits)")[![lchrusciel](https://avatars.githubusercontent.com/u/6213903?v=4)](https://github.com/lchrusciel "lchrusciel (11 commits)")[![loic425](https://avatars.githubusercontent.com/u/8329789?v=4)](https://github.com/loic425 "loic425 (5 commits)")[![bpolaszek](https://avatars.githubusercontent.com/u/5569077?v=4)](https://github.com/bpolaszek "bpolaszek (3 commits)")[![samuel4x4](https://avatars.githubusercontent.com/u/3427855?v=4)](https://github.com/samuel4x4 "samuel4x4 (2 commits)")[![pmartelletti](https://avatars.githubusercontent.com/u/557390?v=4)](https://github.com/pmartelletti "pmartelletti (2 commits)")[![pamil](https://avatars.githubusercontent.com/u/1897953?v=4)](https://github.com/pamil "pamil (2 commits)")[![mtdavidson](https://avatars.githubusercontent.com/u/201792?v=4)](https://github.com/mtdavidson "mtdavidson (1 commits)")[![nicolassing](https://avatars.githubusercontent.com/u/619752?v=4)](https://github.com/nicolassing "nicolassing (1 commits)")[![PapsOu](https://avatars.githubusercontent.com/u/5792207?v=4)](https://github.com/PapsOu "PapsOu (1 commits)")[![rdohms](https://avatars.githubusercontent.com/u/94331?v=4)](https://github.com/rdohms "rdohms (1 commits)")[![ruudy-es](https://avatars.githubusercontent.com/u/6099611?v=4)](https://github.com/ruudy-es "ruudy-es (1 commits)")[![wadjeroudi](https://avatars.githubusercontent.com/u/7465362?v=4)](https://github.com/wadjeroudi "wadjeroudi (1 commits)")[![apoorva-shah](https://avatars.githubusercontent.com/u/24920542?v=4)](https://github.com/apoorva-shah "apoorva-shah (1 commits)")[![Zales0123](https://avatars.githubusercontent.com/u/6212718?v=4)](https://github.com/Zales0123 "Zales0123 (1 commits)")[![cawolf](https://avatars.githubusercontent.com/u/1932623?v=4)](https://github.com/cawolf "cawolf (1 commits)")[![coldic3](https://avatars.githubusercontent.com/u/13316080?v=4)](https://github.com/coldic3 "coldic3 (1 commits)")[![cordoval](https://avatars.githubusercontent.com/u/328359?v=4)](https://github.com/cordoval "cordoval (1 commits)")[![deguif](https://avatars.githubusercontent.com/u/993399?v=4)](https://github.com/deguif "deguif (1 commits)")[![firstred](https://avatars.githubusercontent.com/u/6775736?v=4)](https://github.com/firstred "firstred (1 commits)")

---

Tags

symfonybundlestatemachine

### Embed Badge

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

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

###  Alternatives

[winzou/state-machine-bundle

Bundle for the very lightweight yet powerful PHP state machine

34010.4M15](/packages/winzou-state-machine-bundle)[yohang/finite

A simple PHP Finite State Machine

1.3k3.5M10](/packages/yohang-finite)[pentatrion/vite-bundle

Vite integration for your Symfony app

2725.3M13](/packages/pentatrion-vite-bundle)[gomachan46/state-machine

simple state machine with annotations for PHP, inspired by AASM known as a Ruby state machine.

1893.9k](/packages/gomachan46-state-machine)[ekreative/uuid-extra-bundle

Paramconverter, Normalizer and Form Type for Ramsey Uuid

18168.6k](/packages/ekreative-uuid-extra-bundle)[fsi/datagrid-bundle

FSi Datagrid Bundle

1859.8k1](/packages/fsi-datagrid-bundle)

PHPackages © 2026

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