aw-studio / laravel-states
v1.4.0
2023-09-11 13:11 UTC
Requires
- illuminate/database: ^8.0 | ^9.0
- illuminate/support: ^8.0 | ^9.0
Requires (Dev)
- mockery/mockery: ^1.4
- orchestra/testbench: ^6.13
- phpunit/phpunit: ^9.4
This package is auto-updated.
Last update: 2024-09-11 15:25:35 UTC
README
一个用于在eloquent Models中利用有限状态模式的包。
该包将所有状态存储在数据库表中,因此可以追踪所有状态变化及其对应的时间。由于状态通过关系映射,当模型需要新的状态时,无需创建额外的迁移。
建议
尽可能使用状态!状态可以用作代替布尔值,如 active
或时间戳,如 declined_at
或 deleted_at
$product->state->is('active');
这样你还可以知道何时发生状态变化到active。同时,你的应用也更具可扩展性,如果需要,可以简单地添加额外的状态。
目录
设置
- 通过composer安装包
composer require aw-studio/laravel-states
- 发布所需的资源
php artisan vendor:publish --tag="states:migrations"
- 运行迁移
php artisan migrate
基础知识
- 创建状态
class BookingState extends State { const PENDING = 'pending'; const FAILED = 'failed'; const SUCCESSFULL = 'successfull'; const INITIAL_STATE = self::PENDING; const FINAL_STATES = [self::FAILED, self::SUCCESSFULL]; }
- 创建转换类
class BookingStateTransitions extends State { const PAYMENT_PAID = 'payment_paid'; const PAYMENT_FAILED = 'payment_failed'; }
- 定义允许的转换
class BookingState extends State { // ... public static function config() { self::set(BookingStateTransition::PAYMENT_PAID) ->from(self::PENDING) ->to(self::SUCCESSFULL); self::set(BookingStateTransition::PAYMENT_FAILED) ->from(self::PENDING) ->to(self::FAILED); } }
- 设置你的模型
use AwStudio\States\Contracts\Stateful; use AwStudio\States\HasStates; class Booking extends Model implements Stateful { use HasStates; protected $states = [ 'state' => BookingState::class, 'payment_state' => ..., ]; }
使用方法
获取当前状态
$booking->state->current(); // "pending" (string) $booking->state; // "pending"
确定当前状态是否为给定状态
if($booking->state->is(BookingState::PENDING)) { // }
确定当前状态是否为给定状态之一
$states = [ BookingState::PENDING, BookingState::SUCCESSFULL ]; if($booking->state->isAnyOf($states)) { // }
确定状态是否曾在任何时候为给定状态
if($booking->state->was(BookingState::PENDING)) { // }
执行转换
执行状态转换
$booking->state->transition(BookingStateTransition::PAYMENT_PAID);
通过设置fail为false
来防止在当前状态不允许给定转换时抛出异常
$booking->state->transition(BookingStateTransition::PAYMENT_PAID, fail: false);
存储有关转换原因的附加信息。
$booking->state->transition(BookingStateTransition::PAYMENT_PAID, reason: "Mollie API call failed.");
确定当前状态是否允许给定转换
$booking->state->can(BookingStateTransition::PAYMENT_PAID);
在事务开始时锁定当前状态以更新,以确保在事务完成之前无法通过同时请求修改状态
DB::transaction(function() { // Lock the current state for update: $booking->state->lockForUpdate(); // ... });
预加载
重新加载当前状态
$booking->state->reload();
预加载当前状态
Booking::withCurrentState(); Booking::withCurrentState('payment_state'); $booking->loadCurrentState(); $booking->loadCurrentState('payment_state');
查询方法
过滤具有或不具有当前状态的模型
Booking::whereStateIs('payment_state', PaymentState::PAID); Booking::orWhereStateIs('payment_state', PaymentState::PAID); Booking::whereStateIsNot('payment_state', PaymentState::PAID); Booking::orWhereStateIsNot('payment_state', PaymentState::PAID); Booking::whereStateWas('payment_state', PaymentState::PAID); Booking::whereStateWasNot('payment_state', PaymentState::PAID);
接收状态变化
$booking->states()->get() // Get all states. $booking->states('payment_state')->get() // Get all payment states.
观察者事件
在模型观察者中监听状态变化或转换
class BookingObserver { public function stateSuccessfull(Booking $booking) { // Gets fired when booking state changed to successfull. } public function paymentStatePaid(Booking $booking) { // Gets fired when booking payment_state changed to paid. } public function stateTransitionPaymentPaid(Booking $booking) { // Gets fired when state transition payment_paid gets fired. } }
静态方法
BookingState::whereCan(BookingStateTransition::PAYMENT_PAID); // Gets states where from where the given transition can be executed. BookingState::canTransitionFrom('pending', 'cancel'); // Determines if the transition can be executed for the given state.