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

ActiveCakephp-plugin[Utility &amp; Helpers](/categories/utility)

tsmsogn/cakephp-state-machine
=============================

StateMachineBehavior for CakePHP

1.1(12y ago)1563[3 issues](https://github.com/tsmsogn/cakephp-state-machine/issues)[1 PRs](https://github.com/tsmsogn/cakephp-state-machine/pulls)MITPHPPHP &gt;=5.3.0

Since Oct 2Pushed 7y ago2 watchersCompare

[ Source](https://github.com/tsmsogn/cakephp-state-machine)[ Packagist](https://packagist.org/packages/tsmsogn/cakephp-state-machine)[ Docs](https://github.com/davidsteinsland/cakephp-state-machine)[ RSS](/packages/tsmsogn-cakephp-state-machine/feed)WikiDiscussions master Synced 4w ago

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

CakePHP State Machine
=====================

[](#cakephp-state-machine)

[![Build Status](https://camo.githubusercontent.com/ebe4d8a9eb43f4095fb2a567e08a91f0c6f75466d639bf34bcdbb035bcddbae2/68747470733a2f2f7472617669732d63692e6f72672f74736d736f676e2f63616b657068702d73746174652d6d616368696e652e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/tsmsogn/cakephp-state-machine)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/1ec5109c847311e3b78dc9ca2d7111ed8ee715805d8b3a69acf9db73556c3828/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f74736d736f676e2f63616b657068702d73746174652d6d616368696e652f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/tsmsogn/cakephp-state-machine/?branch=master)

Documentation is not finished yet either. See the tests if you want to learn something, as all aspects of the state machine is tested there.

What is a State Machine?
------------------------

[](#what-is-a-state-machine)

[http://en.wikipedia.org/wiki/State\_machine](http://en.wikipedia.org/wiki/State_machine)

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

[](#installation)

First you need to alter the tables of the models you want to use StateMachine:

```
ALTER TABLE `vehicle` ADD `state` VARCHAR(50) NULL;
ALTER TABLE `vehicle` ADD `previous_state` VARCHAR(50) NULL;
```

Features
--------

[](#features)

- Callbacks on states and transitions
- Custom methods may be added to your model
- `is($state)`, `can($transition)`, `on($transition, 'before|after', callback)` and `when($state, callback)` methods allows you to control the whole flow. `transition($transition)` is used to move between two states.
- Roles and rules
- Graphviz

### Callbacks

[](#callbacks)

You can add callbacks that will fire before/after a transition, and before/after a state change. This can either be done manually with `$this->on('mytransition', 'before', funtion() {})`, or you can add a method to your model:

```
public function onBeforeTransition($currentState, $previousState, $transition) {
    // will fire on all transitions
}

public function onAfterIgnite($currentState, $previousState, $transition) {
    // will fire after the ignite transition
}
```

The state callbacks are a little different:

```
public function onStateChange($newState) {
    // will fire on all state changes
}

public function onStateIdling($newState) {
    // will fire on the idling state
}
```

Naming conventions
------------------

[](#naming-conventions)

- Transitions and states in `$transitions` should be **lowercased** and **underscored**. The method names are in turn camelized.

    Example:

```
    shift_up   => canShiftUp() => shiftUp()
    first_gear => isFirstGear()

```

How to Use
----------

[](#how-to-use)

```
App::uses('StateMachineBehavior', 'StateMachine.Model/Behavior');

class VehicleModel extends AppModel {

	public $useTable = 'Vehicle';

	public $actsAs = array('StateMachine.StateMachine');

	public $initialState = 'parked';

	public $transitionRules = array(
        'ignite' => array(
 			'role' => array('driver'),
			'depends' => 'has_key'
		)
	);

	public $transitions = array(
		'ignite' => array(
			'parked' => 'idling',
			'stalled' => 'stalled'
		),
		'park' => array(
			'idling' => 'parked',
			'first_gear' => 'parked'
		),
		'shift_up' => array(
			'idling' => 'first_gear',
			'first_gear' => 'second_gear',
			'second_gear' => 'third_gear'
		),
		'shift_down' => array(
			'first_gear' => 'idling',
			'second_gear' => 'first_gear',
			'third_gear' => 'second_gear'
		),
		'crash' => array(
			'first_gear' => 'stalled',
			'second_gear' => 'stalled',
			'third_gear' => 'stalled'
		),
		'repair' => array(
			'stalled' => 'parked'
		),
		'idle' => array(
			'first_gear' => 'idling'
		),
		'turn_off' => array(
			'all' => 'parked'
		)
	);

    public function __construct($id = false, $ds = false, $table = false) {
        parent::__construct($id, $ds, $table);
        $this->on('ignite', 'after', function($prevState, $nextState, $transition) {
            // the car just ignited!
        });
    }

    // a shortcut method for checking if the vehicle is moving
    public function isMoving() {
        return in_array($this->getCurrentState(), array('first_gear', 'second_gear', 'third_gear'));
    }

    // the dependant function for "ignite"
	public function hasKey($role) {
		return $role == 'driver';
	}

}
```

With the model above, we have the following methods:

```
isParked()    onStateParked()
isStalled()   onStateStalled()
ignite()      canIgnite()         onBeforeIgnite()    onAfterIgnite()
park()        canPark()           onBeforePark()      onAfterPark()
isFirstGear() onStateFirstGear()
shiftUp()     canShiftUp()        onBeforeShiftUp()   onAfterShiftUp()

....

```

```
class Controller .... {
    public function method() {
        $this->Vehicle->create();
        $this->Vehicle->save(array(
            'Vehicle' => array(
                'title' => 'Toybota'
            )
        ));
        // $this->Vehicle->getCurrentState() == 'parked'
		if ($this->Vehicle->canIgnite(null, 'driver')) {
       	 	$this->Vehicle->ignite(null, 'driver');
       		$this->Vehicle->shiftUp();
        	// $this->Vehicle->getCurrentState() == 'first_gear'
		}
    }
}
```

Graphviz
--------

[](#graphviz)

Here's how to state machine of the Vehicle would look like if you saved:

```
$model->toDot()
```

into `fsm.gv` and ran:

```
dot -Tpng -ofsm.png fsm.gv
```

[![](fsm.png)](fsm.png)

History
-------

[](#history)

- Support PHP 5.3
- Add param $id to `is($state)`, `can($transition)` and `transition($transition)` methods. It specifies record to be read

###  Health Score

24

—

LowBetter than 31% of packages

Maintenance0

Infrequent updates — may be unmaintained

Popularity12

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~616 days

Total

4

Last Release

2804d ago

Major Versions

1.1 → 2.x-dev2018-01-18

2.x-dev → 3.x-dev2018-10-25

### Community

Maintainers

![](https://www.gravatar.com/avatar/7eac05b31b47cce78a6dfdc727bfbecb290bb12b1591cc5be7e1ce63e25666d5?d=identicon)[tsmsogn](/maintainers/tsmsogn)

---

Top Contributors

[![tsmsogn](https://avatars.githubusercontent.com/u/595966?v=4)](https://github.com/tsmsogn "tsmsogn (49 commits)")[![davidsteinsland](https://avatars.githubusercontent.com/u/125661?v=4)](https://github.com/davidsteinsland "davidsteinsland (41 commits)")[![FrodeMMeling](https://avatars.githubusercontent.com/u/3490043?v=4)](https://github.com/FrodeMMeling "FrodeMMeling (29 commits)")[![linc01n](https://avatars.githubusercontent.com/u/667272?v=4)](https://github.com/linc01n "linc01n (1 commits)")

---

Tags

cakephpstate-machinecakephpstatemachine

### Embed Badge

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

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

###  Alternatives

[helsingborg-stad/municipio

A bootstrap theme for creating municipality sites.

4028.3k10](/packages/helsingborg-stad-municipio)[mautic/core

Mautic Open Source Distribution

9.8k2.6k9](/packages/mautic-core)[mediawiki/maps

Adds various mapping features to MediaWiki

78149.7k3](/packages/mediawiki-maps)[civicrm/civicrm-drupal-8

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

19246.3k2](/packages/civicrm-civicrm-drupal-8)[altis/core

Core module for Altis

19222.5k2](/packages/altis-core)[humanmade/popup

An popup and tooltip dialog block utility, multiple trigger options, and supports anchor placements

146.6k](/packages/humanmade-popup)

PHPackages © 2026

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