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

如何在Doctrine的postLoad事件中获取当前用户?

问题描述

尝试创建监听postLoad事件的监听器,需要在其中获取当前用户,但使用TokenStorageInterface或Security组件时返回值均为null。

配置文件(services.yaml)

entity_encryption_listener:
    class: 'App\EventListener\EntityEncryptionListener'
    arguments:
        - 'secret_key'
    tags:
        - { name: doctrine.event_subscriber }

监听器代码(EntityEncryptionListener)

class EntityEncryptionListener implements EventSubscriber
{
    private $security;
    private $secret;

    public function __construct($secret, Security $security)
    {
        $this->secret = $secret;
        $this->security = $security;
    }
    
    public function getSubscribedEvents()
    {
        return [Events::prePersist, Events::preUpdate, Events::postLoad];
    }

    public function prePersist(LifecycleEventArgs $args)
    {
        $this->getSecret();
        $this->encryptEntity($args);
    }

    public function preUpdate(LifecycleEventArgs $args)
    {
        $this->getSecret();
        $this->encryptEntity($args);
    }

    public function postLoad(LifecycleEventArgs $args)
    {
        $user = $this->security->getUser();
        //dd($user);
        $this->getSecret();
        $this->decryptEntity($args);
    }
}
解决思路
  • 修正服务作用域与注入方式
    默认Doctrine事件订阅者是单例服务,初始化时无请求上下文,无法获取用户。需改用请求作用域的代理类并启用延迟加载:
    修改services.yaml:

    entity_encryption_listener:
        class: 'App\EventListener\EntityEncryptionListener'
        arguments:
            - 'secret_key'
            - '@security.helper'
        tags:
            - { name: doctrine.event_subscriber }
        lazy: true
    

    监听器中替换注入类:

    use Symfony\Component\Security\Core\SecurityHelper;
    
    class EntityEncryptionListener implements EventSubscriber
    {
        private $securityHelper;
        private $secret;
    
        public function __construct($secret, SecurityHelper $securityHelper)
        {
            $this->secret = $secret;
            $this->securityHelper = $securityHelper;
        }
    
        public function postLoad(LifecycleEventArgs $args)
        {
            $user = $this->securityHelper->getUser();
            $this->getSecret();
            $this->decryptEntity($args);
        }
    
        // 其他方法保持不变
    }
    
  • 处理非请求场景
    postLoad可能在命令行、消息队列等无用户上下文的场景触发,需做判断跳过逻辑:

    public function postLoad(LifecycleEventArgs $args)
    {
        $user = $this->securityHelper->getUser();
        if (!$user) {
            return;
        }
        $this->getSecret();
        $this->decryptEntity($args);
    }
    
  • 延迟获取TokenStorage(备选方案)
    若坚持使用TokenStorageInterface,可通过容器延迟获取,避免初始化时注入:

    use Psr\Container\ContainerInterface;
    use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
    
    class EntityEncryptionListener implements EventSubscriber
    {
        private $container;
        private $secret;
    
        public function __construct($secret, ContainerInterface $container)
        {
            $this->secret = $secret;
            $this->container = $container;
        }
    
        public function postLoad(LifecycleEventArgs $args)
        {
            if (!$this->container->has(TokenStorageInterface::class)) {
                return;
            }
            $tokenStorage = $this->container->get(TokenStorageInterface::class);
            $user = $tokenStorage->getToken()?->getUser();
            // 后续逻辑
        }
    }
    

内容的提问来源于stack exchange,提问作者dragonkhanrider

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 16:47:13