libriciel / cakephp-state-machine
CakePHP 3 的 StateMachineBehavior
3.1.0
2020-10-21 15:13 UTC
Requires
- php: >=7.1
- ext-json: *
- cakephp/cakephp: ^3.5 || ^4.0
Requires (Dev)
- phpunit/phpunit: ^6.0 || ^8.5
This package is auto-updated.
Last update: 2024-09-04 14:52:52 UTC
README
文档尚未完成。如果您想了解某些内容,请查看测试,因为那里测试了状态机的所有方面。
什么是状态机?
http://en.wikipedia.org/wiki/State_machine
安装
首先,您需要更改您想使用 StateMachine 的模型的表
ALTER TABLE `vehicles` ADD `state` VARCHAR(50);
ALTER TABLE `vehicles` ADD `previous_state` VARCHAR(50);
特性
- 在状态和转换上调用回调
- 可以添加自定义方法到您的模型中
is($entity, $state)
、can($entity, $transition)
、on($transition, 'before|after', callback)
和when($state, callback)
方法允许您控制整个流程。transition($entity, $transition)
用于在两个状态之间移动。- Graphviz
- (已移除:角色和规则,欢迎提交)
回调
您可以为转换之前/之后和状态更改之前/之后添加回调。这可以通过使用 $this->on('mytransition', 'before', function() {})
手动完成,或者您可以在模型中添加一个方法
public function onBeforeTransition($entity, $currentState, $previousState, $transition) {
// will fire on all transitions
}
public function onAfterIgnite($entity, $currentState, $previousState, $transition) {
// will fire after the ignite transition
}
状态回调略有不同
public function onStateChange($entity, $newState) {
// will fire on all state changes
}
public function onStateIdling($entity, $newState) {
// will fire on the idling state
}
命名规范
在
$transitions
中的转换和状态应该是 小写 和 下划线分隔 的。方法名称则是驼峰式。示例
shift_up => can($entity, 'ShiftUp') => transition($entity, 'ShiftUp')
first_gear => is($entity, 'FirstGear')
如何使用
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\ORM\Entity;
class VehiclesTable extends Table
{
public function initialize(array $config)
{
$this->addBehavior('StateMachine.StateMachine');
$this->on('ignite', 'after', function(Entity $entity, $prevState, $nextState, $transition) {
// the car just ignited!
});
}
public $initialState = 'parked';
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'
)
);
// a shortcut method for checking if the vehicle is moving
public function isMoving(Entity $entity) {
return in_array($this->getCurrentState($entity), array('first_gear', 'second_gear', 'third_gear'));
}
}
class Controller .... {
public function method() {
$this->loadModel('Vehicles');
$entity = $this->Vehicles->newEntity();
$entity->title = 'Toybota';
$this->Vehicles->save($entity);
// $this->Vehicles->getCurrentState($entity) == 'parked'
if ($this->Vehicles->can($entity, 'Ignite')) {
$this->Vehicles->transition($entity, 'Ignite');
$this->Vehicles->transition($entity, 'shiftUp');
// $this->Vehicles->getCurrentState($entity) == 'first_gear'
}
}
}
Graphviz
以下是如何将车辆的有限状态机保存为
$table->toDot()
到 fsm.gv
并运行
dot -Tpng -ofsm.png fsm.gv