Symfony4.3 Workflow初始位置creation的transition_context设置问题
解决Symfony Workflow初始位置"creation"的transition_context设置问题
首先,你的监听器没生效的核心原因是:当你创建新实体并直接设置初始marking为"creation"时,并没有通过Workflow组件的apply()方法执行流转操作,因此Workflow的workflow.fiche.entered.creation事件不会被触发——这个事件只有在通过合法的transition进入creation位置时才会触发,而初始标记的设置不属于Workflow的流转操作范畴。
下面给你几个可行的解决方案:
方案1:手动在实体创建时初始化transition_context
这是最直接的方式,在你创建实体的代码(Controller、Service层)中,手动添加初始的流转记录:
// 假设在Controller中创建实体 use Symfony\Component\Security\Core\Security; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use App\Entity\FicheSynthese; class FicheSyntheseController extends AbstractController { public function create(Security $security, EntityManagerInterface $em) { $fiche = new FicheSynthese(); // 获取当前登录用户 $user = $security->getUser(); // 构造初始流转记录 $initialTransition = [ 'time' => new \DateTime(), 'context' => [ 'user' => $user instanceof UserInterface ? $user->getUsername() : null ], 'new_marking' => 'creation' ]; // 设置到实体的transition_contexts属性 $fiche->setTransitionContexts(json_encode([$initialTransition])); // 别忘了设置初始marking(如果你的实体构造函数没做的话) $fiche->setMarking('creation'); $em->persist($fiche); $em->flush(); // ...后续逻辑 } }
这种方式简单直接,不需要依赖额外的事件监听,适合逻辑比较明确的场景。
方案2:使用Doctrine生命周期事件自动添加初始记录
如果希望所有创建的FicheSynthese实体都自动添加初始流转记录,可以用Doctrine的prePersist事件来实现:
- 创建Doctrine事件订阅器:
use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface; use Doctrine\ORM\Events; use Doctrine\Persistence\Event\LifecycleEventArgs; use Symfony\Component\Security\Core\Security; use App\Entity\FicheSynthese; class FicheSyntheseInitialContextSubscriber implements EventSubscriberInterface { private $security; public function __construct(Security $security) { $this->security = $security; } public function prePersist(LifecycleEventArgs $args) { $entity = $args->getObject(); // 只处理FicheSynthese实体 if (!$entity instanceof FicheSynthese) { return; } // 仅当transition_contexts为空时才添加初始记录 if (empty($entity->getTransitionContexts())) { $user = $this->security->getUser(); $initialEntry = [ 'time' => new \DateTime(), 'context' => [ 'user' => $user instanceof UserInterface ? $user->getUsername() : null ], 'new_marking' => 'creation' ]; $entity->setTransitionContexts(json_encode([$initialEntry])); // 如果初始marking也需要设置,这里也可以加上 $entity->setMarking('creation'); } } public static function getSubscribedEvents() { return [ Events::prePersist, ]; } }
- 注册订阅器(Symfony 4.3会自动识别并注册实现了
EventSubscriberInterface的类,如果你是手动配置,在config/services.yaml中添加):
services: App\EventListener\FicheSyntheseInitialContextSubscriber: arguments: ['@security.helper'] tags: - { name: doctrine.event_subscriber }
这样,每当你持久化一个新的FicheSynthese实体时,Doctrine会自动触发prePersist事件,帮你添加初始的流转记录。
关于你之前的监听器的小问题
顺便提一下你之前的监听器里的几个错误:
- 你注入了
Security $security,但代码里用了$this->tokenStorage,应该改成$this->security->getUser() - 监听器里不能用
$this->get('doctrine')来获取EntityManager,应该通过构造函数注入ManagerRegistry或EntityManagerInterface - 最重要的是,那个事件只在通过Workflow流转进入
creation时触发,初始设置不会触发
内容的提问来源于stack exchange,提问作者Azeann
相关产品推荐
相关产品推荐

