本文目录导读:

在 Laravel 工作流开发中,状态模式确实是核心的底层设计思想,但实际应用中很少直接套用“标准状态模式”的类结构,而是借助 Laravel 特有的工具(如状态机包、Eloquent 事件、管道)来实现更灵活的实现。
核心逻辑:状态模式的定义
标准状态模式允许对象在内部状态改变时改变其行为,这完全符合工作流(Workflow)的需求:
- 每个状态定义允许的转换
- 状态转换时触发业务逻辑
- 对象的行为随当前状态而变化
Laravel 中的实现方案
主流方案:状态机包(如 spatie/laravel-model-states)
这是最接近状态模式的实现:
// 定义状态
class PendingState extends State
{
public function approve(): State
{
$this->performEvent('approve');
return new ApprovedState($this->model);
}
public function reject(): State
{
$this->performEvent('reject');
return new RejectedState($this->model);
}
}
class ApprovedState extends State
{
public function reprocess(): State
{
return new PendingState($this->model);
}
}
// 使用
$order = Order::find(1);
$order->state->transition(new ApprovedState($order));
经典实现:cerbero90/laravel-workflow 或自定义
直接复现 GoF 状态模式的类结构:
// 上下文
class OrderContext
{
private OrderState $state;
public function __construct(Order $order)
{
$this->state = match($order->status) {
'pending' => new PendingState(),
'paid' => new PaidState(),
default => throw new \Exception()
};
}
public function proceed(OrderAction $action): void
{
// 委托给当前状态处理
$this->state->handle($this, $action);
}
public function setState(OrderState $state): void
{
$this->state = $state;
}
}
// 状态接口
interface OrderState
{
public function handle(OrderContext $context, OrderAction $action): void;
}
class PendingState implements OrderState
{
public function handle(OrderContext $context, OrderAction $action): void
{
if ($action->isPay()) {
// 执行业务逻辑
$context->setState(new PaidState());
}
}
}
轻型方案:Eloquent + 策略模式(简易替代)
不严格遵循状态模式,但能实现类似效果:
// Eloquent Model
class Order extends Model
{
protected $states = [
'pending' => PendingHandler::class,
'paid' => PaidHandler::class,
];
// 状态变更验证
protected $validTransitions = [
'pending' => ['paid', 'cancelled'],
'paid' => ['shipped'],
'shipped' => ['delivered'],
];
public function transitionTo(string $newState): void
{
// 检查转换合法性
if (!in_array($newState, $this->validTransitions[$this->status] ?? [])) {
throw new InvalidTransitionException();
}
$this->status = $newState;
$this->save();
// 触发业务逻辑
(new $this->states[$newState]($this))->handle();
}
}
实际项目中的最佳实践
个人推荐的工具栈
- 简单工作流:Eloquent
status字段 +transition()方法 - 复杂工作流:
spatie/laravel-model-states - 业务流程引擎:
symfony/workflow(Laravel 可集成)
关键决策点
| 维度 | 标准状态模式 | Laravel 实用方案 |
|---|---|---|
| 状态数量 | ✅ 2-10 个 | ✅ 任何数量 |
| 转换逻辑复杂性 | 状态越多,类越多 | 配置驱动,易于扩展 |
| 数据持久化 | 需要额外实现 | 天然支持 Eloquent |
| 事件监听 | 需手动实现 | 原生支持 Laravel Events |
| 团队可维护性 | 可能过度工程 | 更适合 Laravel 开发者 |
代码示例(基于 spatie 包)
// app/Models/States/TicketState.php
abstract class TicketState extends State
{
abstract public function statusLabel(): string;
public function assignTo(User $user): void
{
$this->model->assigned_to = $user->id;
$this->model->save();
}
}
// app/Models/States/Pending.php
class Pending extends TicketState
{
public function statusLabel(): string
{
return '待处理';
}
public function startWork(): State
{
// 验证权限
// 记录日志
event(new TicketStarted($this->model));
return new InProgress($this->model);
}
}
// Model
class Ticket extends Model
{
use HasStates;
protected $casts = [
'state' => TicketState::class,
];
public function startWork(): void
{
// 转换状态,自动验证合法性
$this->state->transitionTo(InProgress::class);
}
}
Laravel 工作流在概念上完全使用状态模式,但在实现上:
✅ 推荐使用:
spatie/laravel-model-states(接近标准状态模式)- Eloquent + 自定义状态验证(简易场景)
❌ 不推荐:
- 手动实现完整的 GoF 状态模式代码结构(复杂且不必要)
- 在单个控制器/Service 中写
if/else处理所有状态转换
核心原则:利用 Laravel 生态提供的工具(状态机包、Eloquent、事件),而不是重新发明轮子,这能让你获得状态模式的所有优点(可扩展、行为封装、状态转换可控),同时保持 Laravel 代码的简洁和可维护性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播