byjg / statemachine
创建简单的状态机
4.9.0
2023-05-21 22:46 UTC
Requires (Dev)
- phpunit/phpunit: 5.7.*|7.4.*|^9.5
This package is auto-updated.
Last update: 2024-09-16 05:33:49 UTC
README
该组件实现了有限状态机,可以定义多个状态并将它们分组在一系列转换(从一个状态到另一个状态)中。此外,每个状态都可以有一个条件,允许转移到另一个状态。
与其他状态机不同,此实现没有初始或最终状态。
基本示例
让我们使用以下示例。
我们有状态A、B、C和D,以及它们可能的转换。
首先,我们创建状态
$stA = new State("A"); $stB = new State("B"); $stC = new State("C"); $stD = new State("D");
然后,我们定义转换。请注意,每个转换对象都可以有一个接收混合类型 data
的闭包。此闭包需要返回 true
或 false
,允许或不允许转换。
$transitionA_B = new Transition($stA, $stB); $transitionA_C = new Transition($stA, $stC); $transitionB_D = new Transition($stB, $stD, function($data) { return !is_null($data); });
在创建状态和转换之后,我们可以创建状态机
$stateMachine = FiniteStateMachine::createMachine() ->addTransition($transitionA_B) ->addTransition($transitionA_C) ->addTransition($transitionB_D);
我们可以使用 canTransition($from, $to)
方法验证转换。一些示例
$stateMachine->canTransition($stA, $stB); // returns true $stateMachine->canTransition($stA, $stC); // returns true $stateMachine->canTransition($stA, $stD); // returns false $stateMachine->canTransition($stB, $stA); // returns false $stateMachine->canTransition($stB, $stD); // returns false $stateMachine->canTransition($stB, $stD, ["some_info"]); // returns true $stateMachine->canTransition($stC, $stD); //returns false
我们还可以检查状态是否为初始或最终状态
$stateMachine->isInitial($stA); // returns true $stateMachine->isInitial($stB); // returns false $stateMachine->isFinal($stA); // returns false $stateMachine->isFinal($stC); // returns true $stateMachine->isFinal($stD); // returns true
创建状态机的其他方法
或者,您可以使用以下参数使用 createMachine
工厂方法创建状态机
$stateMachine = FiniteStateMachine::createMachine( [ ['A', 'B'], ['A', 'C'], ['B', 'D', function($data) { return !is_null($data); }] ] );
使用自动转换
该组件的另一个特性是,根据您当前的状态以及传递给状态机的数据,它可以决定您可能进入的下一个状态。
让我们分析以下状态。
只有在满足某些条件的情况下,转换才可行。因此,让我们创建状态、可能的转换及其条件。
// States: $stInitial = new State("__VOID__"); $stInStock = new State("IN_STOCK"); $stLastUnits = new State("LAST_UNITS"); $stOutOfStock = new State("OUT_OF_STOCK"); // Transitions: $transitionInStock = Transition::create($stInitial, $stInStock, function ($data) { return $data["qty"] >= $data["min_stock"]; }); $transitionLastUnits = Transition::create($stInitial, $stLastUnits, function ($data) { return $data["qty"] > 0 && $data["qty"] < $data["min_stock"]; }); $transitionOutOfStock = Transition::create($stInitial, $stOutOfStock, function($data) { return $data["qty"] == 0; }); // Create the Machine: $stateMachine = FiniteStateMachine::createMachine() ->addTransition($transitionInStock) ->addTransition($transitionLastUnits) ->addTransition($transitionOutOfStock);
autoTransitionFrom
方法将检查是否可以使用实际数据执行转换以及转换到哪个状态。
$stateMachine->autoTransitionFrom($stInitial, ["qty" => 10, "min_stock" => 20])); // returns LAST_UNITS $stateMachine->autoTransitionFrom($stInitial, ["qty" => 30, "min_stock" => 20])); // returns IN_STOCK $stateMachine->autoTransitionFrom($stInitial, ["qty" => 00, "min_stock" => 20])); // returns OUT_OF_STOCK
自动转换后,返回的状态对象具有 ->getData()
,其中包含用于验证的数据。
此外,您还可以使用闭包创建处理状态的转换。
例如。
$stN = new State('SOMESTATE', function ($data) { // execute some operation with the data }) // After run and return $stN object // We can do this: $resultState = $stateMachine->autoTransitionFrom('STATE', [... data ...])); $resultState->process(); // This will run the closure defined with the data used to validate it.
其他方法
创建多个转换
$transitions = Transition::createMultiple([$from1, $from2], $to, $condition); $machine = FiniteStateMachine::createMachine() ->addTransitions($transitions);
从特定状态获取可能的状态
$stateMachine->possibleTransitions($stA);
获取状态对象
// Return null if doesn't exist, otherwise return the object State $state = $stateMachine->state('OUT_OF_STOCK');
安装
composer require "byjg/statemachine"