tsmsogn / cakephp-state-machine
CakePHP的状态机行为
1.1
2013-10-03 12:19 UTC
Requires
- php: >=5.3.0
- composer/installers: *
Requires (Dev)
- satooshi/php-coveralls: dev-master
This package is auto-updated.
Last update: 2024-08-29 04:42:53 UTC
README
文档尚未完成。如果您想了解一些内容,请查看测试,因为所有状态机的方面都在那里进行了测试。
什么是状态机?
http://en.wikipedia.org/wiki/State_machine
安装
首先,您需要更改想要使用状态机的模型表
ALTER TABLE `vehicle` ADD `state` VARCHAR(50) NULL; ALTER TABLE `vehicle` ADD `previous_state` VARCHAR(50) NULL;
功能
- 状态和转换的回调
- 可以将自定义方法添加到您的模型中
is($state)
、can($transition)
、on($transition, 'before|after', callback)
和when($state, callback)
方法允许您控制整个流程。transition($transition)
用于在两个状态之间移动。- 角色和规则
- Graphviz
回调
您可以在转换之前/之后和状态更改之前/之后添加回调。这可以通过以下方式手动完成:$this->on('mytransition', 'before', funtion() {})
,或者您可以在模型中添加一个方法
public function onBeforeTransition($currentState, $previousState, $transition) { // will fire on all transitions } public function onAfterIgnite($currentState, $previousState, $transition) { // will fire after the ignite transition }
状态回调略有不同
public function onStateChange($newState) { // will fire on all state changes } public function onStateIdling($newState) { // will fire on the idling state }
命名约定
-
在
$transitions
中的转换和状态应该是小写
和下划线
。方法名称随后采用驼峰式。示例
shift_up => canShiftUp() => shiftUp()
first_gear => isFirstGear()
如何使用
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'; } }
使用上述模型,我们有以下方法
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
以下是如果保存到fsm.gv
并运行时,车辆的州机将如何看起来
$model->toDot()
的
dot -Tpng -ofsm.png fsm.gv
历史记录
- 支持PHP 5.3
- 向
is($state)
、can($transition)
和transition($transition)
方法添加参数$id。它指定要读取的记录