ibraheem-ghazi / stager
Laravel eloquent状态机
1.5.1
2019-05-02 08:33 UTC
Requires
- php: >=7.0.0
Requires (Dev)
- phpunit/phpunit: ~4.0|~5.0
README
这是一个用于eloquent模型的Laravel 5.6包。其目的是为模型添加状态机功能
特性
- 所有状态机在一个配置文件中
- 状态定义为名称,值
- 从多个状态进行转换
- 转换影响相关模型
- 按照你定义的X次运行一次计划
- 根据状态和上次状态更改时间进行转换计划
- 计划支持根据状态运行命令
- 支持共享特性以共享属性或覆盖{一些}stager方法
- 支持转换前后的事件
- 支持访问转换之前额外的执行或额外条件
- 自动生成ide帮助文件用于魔术函数
- [新]受保护的转换
- [新]转换前关系状态检查器
- [新]支持集合转换
安装
composer require ibraheem-ghazi/stager
php artisan vendor:publish --provider="IbraheemGhazi\Stager\StagerServiceProvider"
配置
- 为了添加状态机,您必须在
config/state-machine.php
中定义它
#####注意
- 每个状态由生成器定义一个常量
- 每个状态必须具有当前模型的唯一值,以便在获取当前状态名称时不会与其他重叠。
- state-column和init-state属性是可选的,默认情况下state-column = state,init-state默认为第一个状态
- 每个属性键必须使用短横线命名法
<?php /** * On each modification happened to this config file you must run artisan command stager:generate to update files and ide helpers * NOTE: any key must be in kebab-case only */ return [ 'config'=>[ 'ide-helper-path'=>'stager-methods-ide-helper.php',//where to save ide helper file (currently in root) 'fail-throw-exception'=>true, //useful for debug , for production its better to turn it off 'schedule-cronjob'=>'0 * * * *', //run cron job every hour once to handle schedule 'unauthorized-gaurd-exception'=>true,//should throw unauthorized exception if guard requesting this transition is not in guard array , if false then can method only return false without exception //generator config 'constants-prefix'=>'STATE_', // 'shared-trait'=>[ // you can use this a trait to add shared functionality to all models that use stager // or to override scopeStateChangeWithin , getStateChangedAt functions // \App\Traits\SharedTrait::class, ], ], //////////////////////////////////////////// \App\Payment::class => [ 'state-column'=>'state', //(optional, default: state) 'init-state'=>'pending',//(optional, default: the first defined state 'states' => [ //state-name => numeric value 'pending' =>1, 'payment-accepted'=>2, 'in-progress'=>3, 'ended' => 4, ], 'schedules'=>[ //state-name 'pending'=>[ //if last state change time has passed trigger-delay then it will be included in transition run // for example: run transition for all payments that has state 'pending' and changed from 2 days or more 'trigger-delay' =>[ 'time-modifier'=>"DAY", 'interval'=>2 ], // the transition to be run on each row apply this schedule requirement (state , last state change time) 'transition'=>'payment-success', // run commands after transition excuted 'commands'=>[ 'command:subcommand'=>['param1'=>'val1'], ] ], ], 'transitions' => [ 'payment-success' => [ 'from' => 'pending', 'to' => 'payment-accepted', 'relation-state-condition'=>[ //relation class must be defined here in state-machine config 'some-realtion'=>'status' ], 'guard'=>['web'],//array of guards or string equal to '*' [default = '*'] //todo: affection class 'affect'=>[ //relation => transiojn_of_relation 'order' => 'waiting-seller' ], ], 'seller-accept' => [ 'from' => 'payment-accept', 'to' => 'in-progress', ], 'finish' => [ 'from' => 'in-progress', 'to' => 'ended', ], 'canceled' => [ 'from' => 'pending', 'to' => 'ended', ], ], ], ];
- 每次更新配置文件时,您都必须运行
$ php artisan stager:generate
-C or --clean clean auto generated code from all registered models
-M or -model \App\MyModel clean auto generated code from sepcified model
此命令将自动修改实际模型文件,并添加所需的use
语句和从状态写入所需的常量
//an example of auto-generated data to model
<?php
namespace App;
use \IbraheemGhazi\Stager\Traits\Stager;
use Illuminate\Database\Eloquent\Model;
class Payment extends Model
{
/**** AUTO-GENERATED STAGER DATA ****/
use Stager;
const STATE_PENDING = 1;
const STATE_PAYMENT_ACCEPTED = 2;
const STATE_IN_PROGRESS = 3;
const STATE_ENDED = 4;
/**** END OF AUTO-GENERATED STAGER DATA ****/
}
注意:您必须编辑这些注释(或注释本身)之间的任何内容
/**** AUTO-GENERATED STAGER DATA ****/
...
/**** END OF AUTO-GENERATED STAGER DATA ****/
生成器将读取模型文件,如果它有这些注释,则将用新自动生成的代码替换其内容;否则,如果找不到这些注释,它将假设类不包含该数据
共享特性
共享特性用于为所有使用stager的模型定义共享属性,例如,如果您想添加一个关系,它主要定义了这样,您可以轻松覆盖2个Stager方法以获取最后状态更改时间
getStateChangedAt() 获取状态最后更改的时间
paramters : -
scopeStateChangeWithin($query, $modifier, $interval) 范围以获取X天内的更改行,例如
paramters :
* $query = default query paramter for scope from laravel
* $modifier = sql modifiter [YEAR, MONTH, DAY, HOUR, MINUTE, SECOND]
* $interval = integer value define the interval based on modifier
preTransitionNameTransition函数
如果模型中定义了以过渡名的骆驼命名法的函数,并且具有前缀pre
和后缀Transition
,则将在过渡动作之前执行该函数;如果它返回TRUE
,则将完成过渡,否则将终止它
示例:假设您有一个名为:取消订单的过渡
function preCancelOrderTransition(...$args){
}
其中...$args
是从doCancelOrder传递的参数数组
可用函数
可用魔术函数
每个魔术函数都有前缀[is, can, do],后面跟着目标状态或过渡的骆驼命名法
isStateName()
* no parameters required
* return is current model row state equal the state name
canTransitionName()
* no parameters required
* return is current model able to move to given transition from current state or not
doTransitionName()
* accept multiple parameters as you required ( these parameters will be pass to preTransitionNameTransition() )
* execute the transition
* return model or false on failed (note that if `fail-throw-exception` is enabled it will throw an exception instead )
过渡生命周期
- 检查是否可以从当前状态进行转换
- 如果模型定义了preTransitionNameTransition,则将其执行;如果它返回true,则转换将继续,否则将终止(失败)
- 触发beforeTransition事件
- 更新状态
- 如果存在,执行影响
- 触发afterTransition事件