Symfony工作流组件自动触发事件,无需手动dispatch;核心事件包括workflow.article.entered(进入状态)、transitioned(转换完成)、guard(守卫检查)和announce(广播消息),均按workflow.[name].[type]命名,可通过属性、服务标签或运行时方式监听。

Symfony 工作流(Workflow)组件在状态变更时会自动触发一系列事件,你不需要手动 dispatch,只要注册监听器就能响应流程中的关键节点,比如“进入新状态”“转换成功”或“转换失败”。核心在于理解工作流事件的命名规则和触发时机,再用标准方式监听即可。
工作流事件有哪些
每个工作流定义(如 article)都会生成一组带前缀的事件名,格式统一为:
workflow.[workflow_name].[event_type]
-
workflow.article.entered:实体进入某个状态(如
draft、published)时触发,参数是EnteredEvent -
workflow.article.transitioned:一次转换完成(无论目标状态是否变化),参数是
TransitionedEvent -
workflow.article.guard:守卫(guard)检查时触发,可用于动态放行/拦截转换,参数是
GuardEvent -
workflow.article.announce:仅当配置了
announce选项时触发,用于广播通用流程消息
监听工作流事件的三种方式
推荐按项目阶段选择:
-
属性驱动(PHP 8.2+ 推荐):直接在方法上加
#[AsEventListener],无需 YAML 配置#[AsEventListener(event: 'workflow.article.entered', priority: 10)]<br>public function onArticleEntered(EnteredEvent $event): void { ... } -
服务标签注册:在
services.yaml中打标签App\EventListener\ArticleWorkflowListener:<br> tags:<br> - { name: kernel.event_listener, event: workflow.article.entered, method: onEntered } -
运行时动态注册:适合测试或条件性启用
$dispatcher->addListener('workflow.article.transitioned', [$listener, 'onTransition']);
监听器里能做什么
事件对象自带上下文,可安全访问流程数据:
-
$event->getSubject():返回当前流转的实体(如Article实例) -
$event->getMarking():获取当前标记(即状态集合) -
$event->getTransition():获取刚执行的转换对象(含名称、from/to 状态) -
$event->getWorkflowName():返回工作流名(可用于多工作流共存场景)
注意:守卫事件(guard)中调用 $event->setBlocked(true) 可阻止转换继续;其他事件中修改实体后需手动 $em->flush() 持久化。
常见问题排查
监听器不触发?先确认:
- 工作流已正确配置并启用(
framework.workflows中有对应定义) - 实体已应用
WorkflowStamp或通过WorkflowInterface::apply()触发转换 - 监听器类未被自动排除(检查
services.yaml的exclude路径) - 事件名拼写完全匹配(大小写、下划线、workflow 前缀缺一不可)


















