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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:33:13