Symfony 6.4 中创建工作流需定义状态、流转规则和 marking_store(如 method 类型绑定 currentState),配置于 workflow.yaml,实体需声明字段及 getter/setter 并手动映射 ORM 字段,调用 apply() 后必须 flush() 才能持久化。

在 Symfony 6.4 中创建工作流,核心是定义状态(places)、流转规则(transitions)和标记存储方式(marking store),然后通过 YAML 配置注入容器,最后在业务逻辑中调用 apply() 触发状态变更——漏掉 marking_store 配置会导致实体状态无法持久化。
安装并启用 Workflow 组件
运行命令安装组件:composer require symfony/workflow。
该命令会自动注册 Symfony\Bundle\WorkflowBundle\WorkflowBundle,无需手动添加到 bundles.php。
安装后,框架会识别 config/packages/workflow.yaml 并加载配置;若文件不存在,需手动创建。
定义一个基础状态机(state_machine)
在 config/packages/workflow.yaml 中写入以下内容:
framework: workflows: order_processing: type: 'state_machine' audit_trail: { enabled: true } marking_store: type: 'method' property: 'currentState' supports: ['App\Entity\Order'] initial_marking: created places: [created, confirmed, shipped, delivered, cancelled] transitions: confirm: { from: created, to: confirmed } ship: { from: confirmed, to: shipped } deliver: { from: shipped, to: delivered } cancel: { from: [created, confirmed], to: cancelled }
【property: 'currentState' 必须与实体中 getter/setter 方法名严格对应】,例如实体需有 getCurrentState() 和 setCurrentState(string $state);若写成 state 却没提供 getState(),启动时会报错且不提示具体原因。
为实体添加状态字段与访问器
在 App\Entity\Order 中声明私有属性:private string $currentState = 'created';。
生成 getter:public function getCurrentState(): string { return $this->currentState; }。
生成 setter:public function setCurrentState(string $currentState): void { $this->currentState = $currentState; }。
这一步不能省略:Doctrine 不会自动映射 currentState 到数据库字段,你必须手动在 ORM 映射中添加 @ORM\Column(type: "string"),否则 save() 后状态丢失。
在控制器中触发状态流转
方法一:通过服务定位器注入工作流
在控制器方法参数中直接类型提示:WorkflowInterface $orderProcessingWorkflow,Symfony 自动按服务 ID workflow.order_processing 注入。
调用:$orderProcessingWorkflow->apply($order, 'confirm');。
方法二:使用 WorkflowRegistry(适用于多工作流场景)
注入 Symfony\Component\Workflow\Registry $registry,然后写:$workflow = $registry->get($order, 'order_processing'); → $workflow->apply($order, 'ship');。
注意:若实体被多个 workflow 支持(如同时支持主流程和退款子流程),$registry->get($order) 默认返回第一个匹配项,【务必显式传入 workflow 名称字符串】,否则可能误用错误的工作流定义。
验证状态是否成功变更
第一步:调用 $workflow->can($order, 'deliver') 检查当前状态是否允许执行该 transition。
第二步:执行 $workflow->apply($order, 'deliver')。
第三步:立即调用 $em->flush() 持久化变更——因为 apply() 只修改内存中的 marking,不自动写库。
若跳过 flush(),下次从数据库 reload 实体时,getCurrentState() 仍返回旧值;这个坑没有报错,仅表现为“状态看似没变”。


















