php 有限狀態機使用說明
$config = array(
'graph' => 'myGraphA', // Name of the current graph - there can be many of them attached to the same object
'property_path' => 'stateA', // Property path of the object actually holding the state
'states' => array(
'checkout',
'pending',
'confirmed',
'cancelled'
),
'transitions' => array(
'create' => array(
'from' => array('checkout'),
'to' => 'pending'
),
'confirm' => array(
'from' => array('checkout', 'pending'),
'to' => 'confirmed'
),
'cancel' => array(
'from' => array('confirmed'),
'to' => 'cancelled'
)
),
'callbacks' => array(
'guard' => array(
'guard-cancel' => array(
'to' => array('cancelled'), // Will be called only for transitions going to this state
'do' => function() { var_dump('guarding to cancelled state'); return false; }
)
),
'before' => array(
'from-checkout' => array(
'from' => array('checkout'), // Will be called only for transitions coming from this state
'do' => function() { var_dump('from checkout transition'); }
)
),
'after' => array(
'on-confirm' => array(
'on' => array('confirm'), // Will be called only on this transition
'do' => function() { var_dump('on confirm transition'); }
),
'to-cancelled' => array(
'to' => array('cancelled'), // Will be called only for transitions going to this state
'do' => function() { var_dump('to cancel transition'); }
),
'cancel-date' => array(
'to' => array('cancelled'),
'do' => array('object', 'setCancelled'),
),
)
)
);
各個屬性說明
1'property_path' => 'stateA'
需要在 DomainObject
物件中定義,如:
class DomainObject
{
private $stateA = 'checkout';//初始狀態
public function getStateA()
{
return $this->stateA;
}
public function setStateA($state)
{
$this->stateA = $state;
}
}
2 states
定義所有可能的狀態
'states' => array(
'checkout',
'pending',
'confirmed',
'cancelled'
),
3 transitions
定義了執行動作後的狀態變化
'transitions' => array(
'create' => array(
'from' => array('checkout'),
'to' => 'pending'
),
'confirm' => array(
'from' => array('checkout', 'pending'),
'to' => 'confirmed'
),
'cancel' => array(
'from' => array('confirmed'),
'to' => 'cancelled'
)
),
4 callbacks
定義了什麼時候執行相對應的回撥
'callbacks' => array(
'guard' => array(
'guard-cancel' => array(
'to' => array('cancelled'), // Will be called only for transitions going to this state
'do' => function() { var_dump('guarding to cancelled state'); return false; }
)
),
'before' => array(
'from-checkout' => array(
'from' => array('checkout'), // Will be called only for transitions coming from this state
'do' => function() { var_dump('from checkout transition'); }
)
),
'after' => array(
'on-confirm' => array(
'on' => array('confirm'), // Will be called only on this transition
'do' => function() { var_dump('on confirm transition'); }
),
'to-cancelled' => array(
'to' => array('cancelled'), // Will be called only for transitions going to this state
'do' => function() { var_dump('to cancel transition'); }
),
'cancel-date' => array(
'to' => array('cancelled'),
'do' => array('object', 'setCancelled'),
),
)
)
下面這個定義了是否可以更改到當前狀態,guard-cancel
修飾作用沒有實際意義,執行的時候會掃描整個陣列,當to
的指向狀態是cancelled
時執行do
回撥,當回撥返回true
的時候可以更改到該狀態,類似於中介軟體
'guard' => array(
'guard-cancel' => array(
'to' => array('cancelled'), // Will be called only for transitions going to this state
'do' => function() { var_dump('guarding to cancelled state'); return false; }
)
),
透過guard
之後會先執行before
,陣列的key其修飾作用,執行的時候會迴圈這個陣列,當from
的狀態是checkout
會執行do
回撥,
'before' => array(
'from-checkout' => array(
'from' => array('checkout'), // Will be called only for transitions coming from this state
'do' => function() { var_dump('from checkout transition'); }
)
),
before
執行完之後,接下來開始掃描after
陣列,其key起裝飾作用。有兩種型別一種是on
do
,另一種是to
do
。on
對應的是transitions
的key值,匹配到此key值就執行do
回撥。to
對應的是要轉換到的狀態,匹配到此狀態就執行do
回撥
'after' => array(
'on-confirm' => array(
'on' => array('confirm'), // Will be called only on this transition
'do' => function() { var_dump('on confirm transition'); }
),
'to-cancelled' => array(
'to' => array('cancelled'), // Will be called only for transitions going to this state
'do' => function() { var_dump('to cancel transition'); }
),
'cancel-date' => array(
'to' => array('cancelled'),
'do' => array('object', 'setCancelled'),
),
)
do
回撥有兩種方式一種是回撥,另一種是DomainObject
的方法
'do' => array('object', 'setCancelled'),
對應
class DomainObject
{
private $stateA = 'checkout';//初始狀態
public function getStateA()
{
return $this->stateA;
}
public function setStateA($state)
{
$this->stateA = $state;
}
public function setConfirmedNow()
{
var_dump('I (the object) am set confirmed at '.date('Y-m-d').'.');
}
}
的setConfirmedNow
方法
有三個事件
const PRE_TRANSITION = 'winzou.state_machine.pre_transition';
const POST_TRANSITION = 'winzou.state_machine.post_transition';
const TEST_TRANSITION = 'winzou.state_machine.test_transition';
定義完圖後,設定一個初始狀態,例如把訂單的checkout狀態設定進去DomainObject中,然後操作執行相對應的方法(\$stateMachine->apply('create')),可能執行成功($stateMachine->getState(),設定狀態進入訂單表),也可能執行不成功(錯誤處理),
本作品採用《CC 協議》,轉載必須註明作者和本文連結