crumbls/state-machine
Composer 安装命令:
composer require crumbls/state-machine
包简介
A Laravel state machine package with fluent interface configuration
README 文档
README
A Laravel 11+ package that provides a fluent state machine implementation without requiring Eloquent models. Inspired by Spatie's laravel-model-states but designed to be model-agnostic.
Installation
composer require crumbls/state-machine
Basic Usage
1. Define Your States
<?php use Crumbls\StateMachine\State; use Crumbls\StateMachine\StateConfig; abstract class OrderState extends State { abstract public function color(): string; public static function config(): StateConfig { return parent::config() ->default(Pending::class) ->allowTransition(Pending::class, Processing::class) ->allowTransition(Processing::class, Shipped::class) ->allowTransition(Processing::class, Cancelled::class) ->allowTransition(Shipped::class, Delivered::class) ->allowTransition(Pending::class, Cancelled::class); } } class Pending extends OrderState { public function color(): string { return 'yellow'; } } class Processing extends OrderState { public function color(): string { return 'blue'; } } // ... other state classes
2. Create and Use State Machine
use Crumbls\StateMachine\StateMachine; // Create a new state machine $machine = StateMachine::make(OrderState::class); // Check current state $machine->is(Pending::class); // true // Check if transition is allowed $machine->canTransitionTo(Processing::class); // true // Transition to new state $machine->transitionTo(Processing::class); // Access state methods $machine->getCurrentState()->color(); // 'blue'
3. Working with Context
// Create with initial context $machine = StateMachine::make(OrderState::class, [ 'order_id' => 123, 'user_id' => 456 ]); // Add context during transition $machine->transitionTo(Processing::class, [ 'processed_at' => now(), 'processor_id' => auth()->id() ]); // Access context $context = $machine->getContext();
4. Using the Manager
use Crumbls\StateMachine\StateMachineManager; $manager = app(StateMachineManager::class); // Create named state machine $machine = $manager->create('order-123', OrderState::class); // Retrieve later $machine = $manager->get('order-123'); // Or use facade $machine = StateMachine::create('order-123', OrderState::class);
Advanced Features
Middleware
Add Laravel-style middleware to state transitions for security, validation, and performance monitoring:
use Crumbls\StateMachine\Middleware\RateLimitMiddleware; use Crumbls\StateMachine\Middleware\ValidationMiddleware; use Crumbls\StateMachine\Middleware\TimingMiddleware; public static function config(): StateConfig { return parent::config() ->default(Pending::class) ->allowTransition(Pending::class, Processing::class) ->middleware([ // Rate limiting: max 5 attempts per minute RateLimitMiddleware::perMinutes(5, 1), // Validation: ensure required context ValidationMiddleware::rules([ 'user_id' => 'required|integer', 'payment_confirmed' => 'required|boolean' ]), // Performance monitoring TimingMiddleware::maxExecutionTime(2000) // 2 seconds max ]); }
Available Middleware:
RateLimitMiddleware: Prevents too many transition attemptsValidationMiddleware: Validates context data using Laravel validation rulesThrottleMiddleware: Temporarily blocks transitions after failuresTimingMiddleware: Monitors and limits execution timeLoggingMiddleware: Comprehensive transition logging
Custom Middleware:
Create your own middleware using Laravel's standard pattern:
class CustomAuthMiddleware { public function handle(StateTransitionRequest $request, Closure $next) { if (!auth()->check()) { throw new UnauthorizedException('Authentication required'); } // Add user info to context $request->mergeContext(['authenticated_user' => auth()->id()]); return $next($request); } } // Use in config ->middleware([CustomAuthMiddleware::class])
Guards
Add conditional logic to transitions:
public static function config(): StateConfig { return parent::config() ->default(Pending::class) ->allowTransition(Pending::class, Processing::class) ->guard(Pending::class, Processing::class, function ($state, $context) { return isset($context['payment_confirmed']) && $context['payment_confirmed']; }); }
Callbacks
Add hooks for state transitions:
public static function config(): StateConfig { return parent::config() ->default(Pending::class) ->allowTransition(Pending::class, Processing::class) ->onTransition(Pending::class, Processing::class, function ($state, $context) { // Log transition Log::info('Order processing started', $context); }) ->onEnter(Processing::class, function ($state, $context) { // Send notification Notification::send($context['user'], new OrderProcessingNotification()); }); }
Events
The package fires Laravel events on state transitions:
use Crumbls\StateMachine\Events\StateTransitioned; use Crumbls\StateMachine\Events\AsyncTransitionCompleted; use Crumbls\StateMachine\Events\AsyncTransitionFailed; Event::listen(StateTransitioned::class, function ($event) { // $event->stateMachine // $event->fromState // $event->toState // $event->context }); Event::listen(AsyncTransitionCompleted::class, function ($event) { // $event->stateMachine // $event->fromState // $event->toState // $event->identifier // $event->context });
Async Transitions
Process state transitions in the background using Laravel queues:
Basic Async Transition
// Queue a state transition $job = $machine->transitionToAsync(Processing::class, ['note' => 'async processing']); // With custom queue and delay $job = $machine->transitionToAsync( Processing::class, ['note' => 'processing'], 'order-123', // identifier 'state-transitions', // queue name 60 // delay in seconds );
Async with Auto-Continuation
Automatically continue to the next state when there's only one option:
$job = $machine->transitionToAsyncWithContinuation( Processing::class, ['note' => 'will auto-continue'], 'order-123', 'state-transitions', 0, function ($machine, $from, $to) { // Success callback Log::info("Transitioned from {$from} to {$to}"); }, function ($exception, $toState, $context) { // Failure callback Log::error("Failed to transition to {$toState}: " . $exception->getMessage()); } );
Model Integration
Use the HasStateMachine trait for seamless Eloquent model integration:
use Crumbls\StateMachine\Traits\HasStateMachine; class Order extends Model { use HasStateMachine; protected $fillable = ['state_machine_data', 'customer_id']; public function getStateMachineClass(): string { return OrderState::class; } } // Usage $order = Order::create(['customer_id' => 123]); // Sync transition $order->transitionTo(Processing::class); // Async transition $order->transitionToAsync(Processing::class, ['note' => 'processing async']); // Check state $order->isInState(Processing::class); // true $order->getCurrentState()->color(); // 'blue' // With model-based jobs class ProcessOrderJob implements ShouldQueue { public function __construct(public Order $order) {} public function handle() { // The state machine data is automatically saved/loaded $this->order->transitionTo(Shipped::class); } }
Testing
Run the test suite:
composer test
Requirements
- PHP 8.2+
- Laravel 11+
License
MIT License
crumbls/state-machine 适用场景与选型建议
crumbls/state-machine 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 05 月 06 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「laravel」 「states」 「state-machine」 「transitions」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 crumbls/state-machine 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 crumbls/state-machine 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 crumbls/state-machine 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
PHP extension with Brazilian states and formats for CPF, CNPJ and ZIP
A simple PHP class for United States Postal Service (USPS) addresses
Control your state using enums
Convert and operate with FIPS codes for states, counties, etc.
PHP Countries and Currencies
A workflow manager plugin for FilamentPHP with PHP enum support.
统计信息
- 总下载量: 1
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 48
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-05-06