masterfri / stateful

Laravel 5 的有限状态机实现

v1.1 2017-07-26 13:36 UTC

This package is not auto-updated.

Last update: 2024-09-21 14:32:58 UTC


README

Stateful 是 Laravel 5 有限状态机的另一种实现。它允许以最小的努力将任何类转换为状态实体。这种特定实现的基本概念是,实体的状态变化是由信号触发的,这些信号可以手动发送给实体,也可以映射到事件。

安装

Stateful 可以通过 composer 安装

composer require masterfri/stateful

如果您想将信号映射到事件,您需要在 config/app.php 中注册服务提供者,如下所示

'providers' => [
    ...
    Masterfri\Stateful\Providers\StatefulServiceProvider::class,
]

然后您需要创建 config/stateful.php,内容如下

return [
  'event_mapping' => [
    'eloquent.saving: *' => 'save',
    ...
  ],
];

您可以根据需要定义事件和信号之间的关系。不同的事件可以绑定到同一信号,同样,一个事件也可以触发多个信号。

定义状态实体

Stateful 必须实现接口 Masterfri\Stateful\Contracts\Stateful。Trait Masterfri\Stateful\Traits\StatefulTrait 包含控制实体所需的所有方法,您只需在定义状态机时实现方法 createStateMachine()

public function createStateMachine()
{
  return FSM::build([
    'states' => [ // list of states 
      'state1', // state can be defined without options
      'state2' => [ // or with options
        'initial' => true, // optional, defines that state is initial, there must be exactly one initial state
        'enter' => function($entity) {}, // optional, this function is executed when entity enters the state
        'leave' => function($entity) {}, // optional, this function is executed when entity leaves the state
        'finite' => true, // optional, defines that state is finite, there may be any amount of finite states
      ],
    ],
    'transitions' => [ // list of transitions
      [
        'source', // source state name
        'destination', // destination state name
        'signal', // type of signal that can trigger this transition
        'condition' => function($entity, $signal) {}, // optional, this finction is an additional condition that defines if transition has to be triggered
        'transit' => function($entity) {}, // optional, this function is executed when entity goes through the transition 
      ]
    ],
  ]);
}

以下是一个简单的示例

use Masterfri\Stateful\Contracts\Stateful;
use Masterfri\Stateful\Traits\StatefulTrait;
use Masterfri\Stateful\FSM;

class Order extends Model implements Stateful
{
  use StatefulTrait;
  ...
  public function createStateMachine()
  {
    return FSM::build([
      'states' => [
        'new' => ['initial' => true],
        'placed' => [
          'enter' => function($model) {
            $model->sendCustomerEmail('Your order has been placed', 'placed.tmpl');
          },
        ],
        'processed',
        'shipped' => [
          'enter' => function($model) {
            $model->sendCustomerEmail('Your order has been shipped', 'shipped.tmpl');
          },
        ],
        'completed' => ['finite' => true],
      ],
      'transitions' => [
        // Order is submitted by customer
        ['new', 'placed', 'submit'],
        // Manager processed the order
        ['placed', 'processed', 'process',
          'condition' => function($model) {
            return $model->canBeProcessed();
          }
        ],
        // Manager reviewed order and marked it as non-processable
        ['placed', 'completed', 'process',
          'condition' => function($model) {
            return !$model->canBeProcessed();
          },
          'transit' => function($model) {
            $model->sendCustomerEmail('Sorry your order can not be processed', 'rejected.tmpl');
            $model->markAsRejected();
          }
        ],
        // Manager received information from delivery service and filled out delivery information on the order
        ['processed', 'shipped', 'ship'],
        // Manager received feedback from customer
        ['shipped', 'completed', 'close']
      ]);
  }