Symfony3.4+FOSUserBundle:如何在实体PrePersist/PreUpdate时设置当前登录用户ID
在Symfony 3.4 + FOSUserBundle中自动为Projet实体设置当前登录用户ID
这个需求我之前在Symfony 3.4项目里也碰到过,实体自带的@ORM\PrePersist和@ORM\PreUpdate回调里确实没法直接获取当前登录用户——因为实体本身不应该依赖容器服务。下面是我当时用的可行方案,通过Doctrine的生命周期事件监听器来实现:
步骤1:创建生命周期事件监听器
我们需要写一个监听器类,注入Symfony的TokenStorageInterface来获取当前用户,然后监听Doctrine的prePersist和preUpdate事件,为Projet实体设置用户。
创建src/AppBundle/EventListener/ProjetUserListener.php文件:
namespace AppBundle\EventListener; use AppBundle\Entity\Projet; use Doctrine\ORM\Event\LifecycleEventArgs; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; class ProjetUserListener { private $tokenStorage; // 注入TokenStorage服务,用于获取当前登录用户 public function __construct(TokenStorageInterface $tokenStorage) { $this->tokenStorage = $tokenStorage; } // 处理实体首次持久化的事件 public function prePersist(LifecycleEventArgs $args) { $entity = $args->getEntity(); // 只处理Projet实体 if (!$entity instanceof Projet) { return; } // 获取当前登录用户 $token = $this->tokenStorage->getToken(); if ($token && $user = $token->getUser()) { $entity->setUser($user); } } // 处理实体更新的事件 public function preUpdate(LifecycleEventArgs $args) { $entity = $args->getEntity(); if (!$entity instanceof Projet) { return; } // 这里根据你的业务需求决定:是否在修改项目时,把用户替换为当前登录的用户 $token = $this->tokenStorage->getToken(); if ($token && $user = $token->getUser()) { $entity->setUser($user); // 注意:preUpdate事件中Doctrine已经生成了变更集,修改关联对象后需要手动重新计算 $em = $args->getEntityManager(); $uow = $em->getUnitOfWork(); $uow->recomputeSingleEntityChangeSet($em->getClassMetadata(Projet::class), $entity); } } }
步骤2:配置监听器服务
在app/config/services.yml里注册这个监听器,让Doctrine能识别它:
services: app.projet_user_listener: class: AppBundle\EventListener\ProjetUserListener arguments: ['@security.token_storage'] tags: - { name: doctrine.event_listener, event: prePersist } - { name: doctrine.event_listener, event: preUpdate }
步骤3:调整Projet实体的回调方法
把原来实体里的用户设置逻辑移除,让updatedTimestamps只负责处理时间字段:
/** * @ORM\PrePersist * @ORM\PreUpdate */ public function updatedTimestamps() { $this->setModification(new \DateTime()); if($this->getCreation() == null) { $this->setCreation(new \DateTime()); $this->setSupprime(false); } }
额外注意点
- 确保你的Projet实体已经有
setUser方法,比如:
public function setUser(\AppBundle\Entity\User $user): self { $this->user = $user; return $this; }
- 如果你的业务不需要在更新项目时修改用户,可以删掉
preUpdate方法里的用户设置逻辑,只保留prePersist的部分。
内容的提问来源于stack exchange,提问作者Preciel
相关产品推荐
相关产品推荐

