m1lt0n / in_great_state
易于使用的状态机
v1.0.0
2017-07-26 13:16 UTC
Requires (Dev)
- phpunit/phpunit: ^5.7
This package is not auto-updated.
Last update: 2024-09-20 20:26:21 UTC
README
一个易于使用且灵活的状态机。
InGreatState 是一个简单且非常可扩展的状态机。它不偏不倚,可以与 ORM、Web 框架或独立脚本结合使用。
示例
假设你有一个问题跟踪器。问题可以处于几种状态之一(例如:打开、不会修复、已解决、重新打开等)。当从一个状态转换到另一个状态时,我们想做一些事情(例如:向问题的所有者发送电子邮件等)。通过使用状态机可以轻松组织这样的操作。上述示例的一个例子可以是
<?php // The minimum requirements of a StateFul interface is to implement the // currentState method (that returns the object's current state) and the // setState method (that updates the state of the object). class Issue implements InGreatState\StatefulInterface { private $state; public function __construct() { $this->setState('open'); } public function currentState() { return $this->state; } public function setState($state) { $this->state = $state; echo "Setting state to {$state}" . PHP_EOL; } } // The minimum requirements for a state machine that extends the InGreatState // state machine is to implement the method states (which returns an array of // all the states an object can be) and registerTransitions (which adds all // the allowed state transitions and the actions they trigger). class IssueStateMachine extends InGreatState\StateMachine { public function states() { return ['open', 'wontfix', 'resolved', 'reopened']; } public function registerTransitions() { $this->addTransition()->from('open')->to('resolved')->actions(function ($owner) { echo "Resolving transition from {$owner->currentState()} to resolved" . PHP_EOL; }); $this->addTransition()->from('open')->to('wontfix')->actions(function ($owner) { echo "Resolving transition from {$owner->currentState()} to wontfix" . PHP_EOL; }); } } // Now, we can use the state machine :-) $p = new Issue(); $sm = new IssueStateMachine($p); $sm->transitionTo('resolved');
此代码将问题状态设置为 '已解决',并输出以下短语
- 从打开到已解决的状态转换(由 open->resolved 的转换触发)
- 设置状态为已解决(由 Issue 的 setState 触发)
过渡 API 流畅,允许方法链式调用。如果您想从任何初始状态添加过渡,只需指定最终状态和操作即可
<?php $this->addTransition()->to('wontfix')->actions(function ($owner) { echo "Resolving transition to wontfix" . PHP_EOL; });
上述代码将匹配从任何初始状态到 wontfix 的任何过渡。请注意,所有匹配的过渡操作都将被触发(即找到匹配的过渡后,执行不会停止,因此您可以从 open->closed 等添加多个过渡注册)。
一个重要的注意事项是,在您的闭包中抛出异常被认为是一个好的做法,以停止过渡的执行并避免不一致的数据悄悄进入您的应用程序。另外,如果您在过渡期间(以及您的闭包和/或您的 setState 方法中)在数据库中持久化数据,那么将过渡包装在数据库事务中是一个好主意,以便回滚所有更改并避免不一致的数据结构。
该架构足够灵活,可以适应任何 Web 框架或 ORM 集成,并且很容易添加功能,如状态记录(您可以通过在状态对象的 setState 方法中实现功能将状态转换存储在数据库中或甚至平面文件)。您完全掌控一切!