You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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事件来实现:

  1. 创建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,
        ];
    }
}
  1. 注册订阅器(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:02:00