本文目录导读:

在PHP项目中实现流程设计(通常是工作流引擎或审批流),根据项目规模和复杂度的不同,有多种实现路径,以下是几种从简单到复杂的常见方案。
核心概念:流程设计的三要素
无论采用哪种方案,核心概念通常包括:
- 节点(Node/Task):流程中的每一步(申请、经理审批、HR审批、结束)。
- 连线(Transition/Edge):定义节点之间的流转条件(同意 -> 下一步;驳回 -> 第一步)。
- 实例(Instance):一个具体的流程运行记录。
硬编码流程(适用于简单、固定场景)
适用场景:流程极少变动,逻辑简单(如请假、报销),不涉及可视化配置。
实现方式:将流程逻辑直接写在控制器或服务层代码中。
<?php
// 伪代码演示
class LeaveWorkflow {
public function process(LeaveRequest $request, string $action): void
{
switch ($request->status) {
case 'pending': // 待部门主管审批
if ($action === 'approve') {
if ($request->days > 7) {
// 超过7天,转给总监
$request->updateStatus('director_pending');
} else {
$request->updateStatus('hr_pending');
}
} elseif ($action === 'reject') {
$request->updateStatus('finished_rejected');
}
break;
case 'director_pending': // 总监审批
if ($action === 'approve') {
$request->updateStatus('hr_pending');
}
// ...
break;
case 'hr_pending': // HR审批
if ($action === 'approve') {
$request->updateStatus('finished_approved');
}
break;
}
}
}
优点:实现快速,对数据库无特殊要求,适合极少数固定流程。 缺点:修改流程需要改代码、重新部署,无法应对多变的业务需求。
基于数据库配置的简单流程引擎(灵活、可控)
适用场景:流程会在后台被管理员配置(如通过WordPress插件或自定义后台),但不需要拖拽画流程图。
实现方式:将流程定义存储在数据库表中。
数据库设计(简化版):
wf_definitions(流程定义表):id,name(如“请假流程”),first_node_id。wf_nodes(节点表):id,definition_id,name(如“经理审批”),type(start/approval/end),assignee_type(user/role),assignee_id。wf_transitions(连线表):id,from_node_id,to_node_id,condition_name(如“同意”/“驳回”)。
PHP代码:
// 核心流转函数(简化版)
class WorkflowEngine {
public function processTransition(int $instanceId, int $transitionId): void
{
// 1. 获取当前实例所处的节点
$instance = WorkflowInstance::find($instanceId);
$currentNode = $instance->currentNode();
// 2. 获取用户选择的连线
$transition = WorkflowTransition::find($transitionId);
// 3. 简单条件判断(实际应支持复杂规则)
if ($transition->condition_name === '同意') {
$nextNode = Node::find($transition->to_node_id);
// 4. 更新实例状态到下一个节点
$instance->current_node_id = $nextNode->id;
$instance->save();
// 5. 创建待办任务
if ($nextNode->type === 'approval') {
Task::create([
'instance_id' => $instance->id,
'node_id' => $nextNode->id,
'assignee' => $this->resolveAssignee($nextNode), // 根据角色或用户
'status' => 'pending'
]);
}
} elseif ($transition->condition_name === '驳回') {
// 返回上一个节点(需维护历史记录)
$instance->current_node_id = $this->getPreviousNode($instance);
$instance->save();
// 创建退回待办
}
// 如果下一个节点是 End 类型,则流程结束
if ($nextNode->type === 'end') {
$instance->status = 'completed';
$instance->save();
}
}
}
优点:灵活,修改流程不需要改代码;稳定性高,容易审计和调试。 缺点:无法可视化配置,配置过程需要人员理解表结构或后台列表,对于复杂的并行、会签、条件网关(如根据金额、部门路由)逻辑需要自己实现。
集成第三方可视化流程引擎(推荐、功能强大)
适用场景:需要可视化拖拽配置、支持复杂网关(条件、并行、会签、子流程)、企业级大型系统。
实现方式:使用成熟的流程引擎作为服务,PHP通过API调用(或使用守护进程+消息队列)。不推荐纯PHP完整实现BPMN 2.0引擎(性能和安全风险大)。
推荐方案:Flowable(Java) + 远程调用 + 数据库共享
- 可视化建模:使用Flowable的Modeler(基于Angular的前端),在后台拖拽生成BPMN 2.0 XML。
- 流程引擎服务:运行Flowable(Java)作为独立微服务。
- PHP对接:PHP通过REST API或gRPC与Flowable交互。
// PHP 调用 Flowable API 示例(伪代码)
class WorkflowService {
public function startProcess(string $processKey, array $variables): array
{
// 向Flowable引擎发起请求
$response = HttpClient::post('http://flowable-service:8080/runtime/process-instances', [
'processDefinitionKey' => $processKey,
'variables' => $variables // 如 { "days": 5, "department": "tech" }
]);
return $response->json();
}
public function completeTask(string $taskId, array $variables): void
{
HttpClient::post("http://flowable-service:8080/runtime/tasks/{$taskId}", [
'action' => 'complete',
'variables' => $variables
]);
}
}
优点:
- 成熟稳定:Flowable/Camunda经过大量企业验证,支持BPMN 2.0标准。
- 功能完整:条件路由、并行网关、会签、子流程、计时器、事件监听。
- 可视化:前端有现成的模型编辑器和用户任务处理界面(可嵌入PHP项目)。
缺点:
- 架构复杂:需要维护Java服务。
- 运维成本:额外增加服务部署和维护工作。
轻量级选择:php-workflow(纯PHP轻量库)
如果项目只能使用PHP,且流程相对简单(无需图形化编辑器),可以考虑 sebdesign/php-workflow 或类似库。
use SM\StateMachine\StateMachine;
use SM\Factory\Factory;
use SM\Callback\CallbackFactory;
// 定义状态机配置
$config = [
'graph' => 'my_graph',
'class' => \App\Models\Order::class,
'states' => ['pending', 'processing', 'shipped', 'delivered'],
'transitions' => [
'process' => ['from' => ['pending'], 'to' => 'processing'],
'ship' => ['from' => ['processing'], 'to' => 'shipped'],
'deliver' => ['from' => ['shipped'], 'to' => 'delivered'],
],
'callbacks' => [
'after' => [
'on_process' => [CallbackFactory::build('\App\Workflow\Actions\ProcessAction')]
]
]
];
$factory = new Factory([$config]);
$stateMachine = $factory->get(new Order(), 'my_graph');
$stateMachine->apply('process'); // 触发流转
优点:
- 纯PHP:无外部依赖,部署简单。
- 标准封装:基于Symfony Workflow Component,支持状态机模式与工作流模式。
- 易于集成:附带回调机制,可在状态变更时执行自定义业务逻辑。
缺点:
- 无可视化:需要手动配置 YAML/PHP 数组。
- 不支持并行:天然的模型是串行的(状态机),并行需要额外实现。
- 不适合极复杂BPMN:子流程、多重网关等需要自己扩展。
总结与选型建议
| 方案 | 适用场景 | 复杂度 | 灵活性 | 可视化 | 推荐指数 |
|---|---|---|---|---|---|
| 硬编码 | 1-2个固定流程 | 极低 | 极低 | 无 | ⭐⭐ |
| 数据库配置 | 内部OA、需要后台管理 | 中等 | 较高 | 只有列表配置 | ⭐⭐⭐⭐ |
| Flowable/Camunda | 大型企业ERP、合同、采购 | 高 | 极高 | 有(拖拽) | ⭐⭐⭐⭐⭐ |
| php-workflow | 中等规模、无可视化要求 | 低中 | 高 | 无(配置) | ⭐⭐⭐ |
最推荐的平衡方案(大部分PHP项目适用):
采用 数据库配置 + 自定义简易图形化前端(基于jsPlumb或LogicFlow)。
- 数据库:设计
wf_definition、wf_node、wf_line结构。 - 后端:实现解析流程图的JSON(如
{ nodes: [...], edges: [...] }),运行时根据条件动态计算下一个节点。 - 前端:集成 LogicFlow 或 AntV XFlow(国内常用,文档中文,支持React/Vue),允许管理员拖拽配置。
这种方案不依赖Java服务,纯PHP + 前端绘制,可以满足绝大多数企业级可视化流程需求,也是国内外许多SaaS软件的常见实现方式。