在Laravel项目开发中,复杂业务流程往往涉及多个状态节点的流转和对应的业务规则校验,传统做法容易让控制器或服务层代码变得臃肿。Eloquent Attribute Workflows是一个专门面向Eloquent模型的属性工作流工具,能够将状态流转逻辑和对应的业务处理封装到模型层面,让属性变更自动驱动业务流程执行。

工具安装与基础配置
首先需要通过Composer安装Eloquent Attribute Workflows包,执行以下命令完成安装:
composer require "your-vendor/eloquent-attribute-workflows"
安装完成后,在需要启用工作流的Eloquent模型中引入对应的Trait,并定义工作流的基础配置:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
use VendorEloquentAttributeWorkflowsHasAttributeWorkflows;
class Order extends Model
{
use HasAttributeWorkflows;
// 定义需要启用工作流的属性
protected $workflowAttributes = ['status'];
// 定义status属性的工作流规则
protected function statusWorkflow()
{
return [
'initial' => 'pending', // 初始状态
'transitions' => [
'pending_to_paid' => [
'from' => 'pending',
'to' => 'paid',
'before' => 'checkPaymentValid', // 流转前校验方法
'after' => 'handlePaidOrder', // 流转后处理方法
],
'paid_to_shipped' => [
'from' => 'paid',
'to' => 'shipped',
'before' => 'checkStockEnough',
'after' => 'handleShippedOrder',
],
'shipped_to_completed' => [
'from' => 'shipped',
'to' => 'completed',
'after' => 'handleCompletedOrder',
],
],
];
}
// 支付前校验:检查支付信息是否有效
protected function checkPaymentValid()
{
// 实际业务中可添加支付金额校验、支付渠道校验等逻辑
return !empty($this->payment_sn) && $this->total_amount > 0;
}
// 支付后处理:更新库存、发送支付通知
protected function handlePaidOrder()
{
// 库存扣减逻辑
foreach ($this->items as $item) {
$item->product->decrement('stock', $item->quantity);
}
// 发送支付成功通知
// 通知逻辑代码
}
// 发货前校验:检查库存是否充足
protected function checkStockEnough()
{
foreach ($this->items as $item) {
if ($item->product->stock < $item->quantity) {
return false;
}
}
return true;
}
// 发货后处理:生成物流单号、发送发货通知
protected function handleShippedOrder()
{
$this->logistics_sn = 'LOGI_' . time() . rand(1000, 9999);
// 发送发货通知逻辑
}
// 完成后处理:记录完成时间、更新用户积分
protected function handleCompletedOrder()
{
$this->completed_at = now();
// 用户积分更新逻辑
}
}
工作流的核心运行机制
Eloquent Attribute Workflows的核心逻辑围绕属性变更触发,当修改模型的status属性时,会自动匹配定义好的流转规则:
- 首先检查目标状态是否在允许的流转范围内,避免非法状态变更
- 如果定义了
before方法,会先执行对应校验逻辑,校验不通过则阻止状态变更 - 校验通过后更新属性值,再执行
after定义的后续业务处理逻辑
这种机制让状态流转和业务逻辑强绑定,不需要在控制器中手动调用各种校验和处理方法,减少代码耦合。
实际业务场景应用
以订单状态流转为例,传统的控制器逻辑可能如下:
<?php
namespace AppHttpControllers;
use AppModelsOrder;
use IlluminateHttpRequest;
class OrderController extends Controller
{
public function payOrder(Request $request, $orderId)
{
$order = Order::findOrFail($orderId);
// 手动校验支付信息
if (empty($order->payment_sn) || $order->total_amount <= 0) {
return response()->json(['error' => '支付信息无效'], 400);
}
// 手动更新状态
$order->status = 'paid';
$order->save();
// 手动处理库存和通知
foreach ($order->items as $item) {
$item->product->decrement('stock', $item->quantity);
}
// 通知逻辑
return response()->json(['message' => '支付成功']);
}
}
使用Eloquent Attribute Workflows后,控制器逻辑可以简化为:
<?php
namespace AppHttpControllers;
use AppModelsOrder;
use IlluminateHttpRequest;
class OrderController extends Controller
{
public function payOrder(Request $request, $orderId)
{
$order = Order::findOrFail($orderId);
try {
// 直接修改属性,自动触发工作流逻辑
$order->status = 'paid';
$order->save();
return response()->json(['message' => '支付成功']);
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 400);
}
}
public function shipOrder(Request $request, $orderId)
{
$order = Order::findOrFail($orderId);
try {
$order->status = 'shipped';
$order->save();
return response()->json(['message' => '发货成功']);
} catch (Exception $e) {
return response()->json(['error' => $e->getMessage()], 400);
}
}
}
高级用法扩展
带参数的流转校验
如果流转校验需要额外参数,可以在模型中定义接收参数的方法:
protected function checkPaymentValid($paymentChannel)
{
return $paymentChannel === 'valid_channel' && !empty($this->payment_sn);
}
修改属性时传递参数:
$order->setWorkflowParam('paymentChannel', 'wechat');
$order->status = 'paid';
$order->save();
多属性工作流联动
如果需要多个属性的变更联动触发业务流程,可以在$workflowAttributes中定义多个属性,分别为每个属性定义对应的工作流规则,属性之间可以通过模型方法实现联动逻辑。
注意事项
- 工作流规则定义的方法需要是模型的保护方法或公有方法,确保可以被工作流驱动类调用
- 如果业务中存在跨模型的流程联动,建议结合Laravel的事件系统,在工作流的
after方法中触发对应事件,由事件监听器处理跨模型逻辑 - 状态流转的校验逻辑尽量保持单一职责,避免在一个校验方法中处理过多无关逻辑,方便后续维护扩展
PHPEloquent_Attribute_WorkflowsLaravel业务流程修改时间:2026-06-14 23:24:40