退款子流程需在workflow.yaml中独立定义为state_machine,使用专用字段refundstatus和专属getter,调用时必须显式指定workflow名称order_refund,否则默认获取主流程导致transition不存在错误。

workflow.yaml 里怎么定义退款子流程? 退款不是主订单流程的简单分支,它有独立状态生命周期(申请→审核→打款→完成),必须单独建模为一个 state_machine。直接往主 workflow 的 places 里加 refunding/refunded 会导致状态污染和 guard 冲突。
在 config/packages/workflow.yaml 中新增独立配置:
framework:
workflows:
order_refund:
type: 'state_machine'
audit_trail: enabled: true
marking_store:
type: 'method'
property: 'refundStatus' # 注意:不是主订单的 status 字段
supports:
- App\Entity\Order
places:
- requested
- under_review
- approved
- rejected
- paid_out
- failed
transitions:
request:
from: null
to: requested
review:
from: requested
to: under_review
approve:
from: under_review
to: approved
reject:
from: under_review
to: rejected
payout:
from: approved
to: paid_out
fail:
from: [approved, under_review]
to: failed
关键点:supports 必须包含 Order 类;property 指向退款专用字段(如 $refundStatus),不能复用主流程的 status;from: null 允许从任意状态触发申请,符合业务实际。
实体里怎么同时支持主流程 + 退款子流程?
一个 Order 实体要被两个 workflow 管理,就得提供两套状态读取逻辑。WorkflowRegistry 不会自动区分,全靠你显式传 name。
实体需实现两个 getter:
-
getStatus()返回主流程状态(用于orderworkflow) -
getRefundStatus()返回退款状态(用于order_refundworkflow)
调用时必须指定 workflow 名称:
// 主流程 $mainWorkflow = $this->workflowRegistry->get($order, 'order'); $mainWorkflow->can($order, 'cancel'); <p>// 退款子流程 $refundWorkflow = $this->workflowRegistry->get($order, 'order_refund'); $refundWorkflow->apply($order, 'approve');</p>
漏掉第二个参数 'order_refund',$this->workflowRegistry->get($order) 默认返回第一个匹配的 workflow(通常是主流程),apply('approve') 就会报 “Transition ‘approve’ does not exist”——因为主流程里根本没有这个 transition。
怎么生成 Mermaid 流程图看退款路径?
MermaidDumper 不读 YAML 配置,它只认 PHP 构建的 Definition 对象。YAML 定义的 workflow 必须先加载成 Definition 实例,再喂给 Dumper。
写个命令行脚本(比如 src/Command/GenerateRefundFlowCommand.php):
use Symfony\Component\Workflow\Dumper\MermaidDumper;
use Symfony\Component\Workflow\Registry;
<p>// 获取已注册的 order_refund workflow 实例
$definition = $this->workflowRegistry
->get($order, 'order_refund')
->getDefinition();</p><p>$dumper = new MermaidDumper();
file_put_contents('refund-flow.mmd', $dumper->dump($definition));</p>
运行后得到 refund-flow.mmd,用 VS Code 插件或 Mermaid Live Editor 打开就能看到带节点、箭头、条件标签的可视化图。注意:MermaidDumper 不渲染 guard 条件,那些得靠你在 transition 注释里手动加,比如在 YAML 的 approve transition 下加 metadata: { label: '审核通过(需库存充足)' },再在模板或文档里补充说明。
为什么 refundStatus 改了但数据库没更新?
Workflow 组件只改内存里的 marking,不碰数据库。apply() 后必须手动 flush,且字段名必须和 YAML 里 property 值完全一致。
常见错误链:
- YAML 写
property: 'refund_status',但实体方法叫getRefundStatus()→ Workflow 找不到 setter,静默失败 - 实体用了
private string $refundStatus,但没写setRefundStatus(string $status)→ Doctrine 不知道怎么持久化 - 调用
$workflow->apply($order, 'approve')后忘了$entityManager->flush()→ 状态只存在 PHP 内存里
验证方式:apply() 后立刻 dump $order->getRefundStatus(),值变了但数据库没变,就是漏 flush;值根本没变,就去查 getter/setter 名称是否和 YAML 的 property 对得上。
复杂点在于退款流程常依赖主订单状态(比如只有 delivered 的订单才能申请退款),这种跨 workflow 的 guard 不能写在 YAML 里,得用 PHP 回调,而且要小心 Doctrine Proxy 和 N+1 查询——这比画流程图难得多。











