Symfony 4 Doctrine EventSubscriber 未使用

Mat*_*Dev 1 events doctrine subscriber symfony

尝试注册 Doctrine EventSubscriber 但实际上没有任何内容被触发。

我已在相关实体上设置了注释@ORM\HasLifeCycleCallbacks

这是订阅者:

<?php

namespace App\Subscriber;

use App\Entity\User;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Events;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class UserPasswordChangedSubscriber implements EventSubscriber
{
    private $passwordEncoder;

    public function __construct(UserPasswordEncoderInterface $passwordEncoder)
    {
        $this->passwordEncoder = $passwordEncoder;
    }

     public function getSubscribedEvents()
    {
        return [Events::prePersist, Events::preUpdate, Events::postLoad];
    }

    public function prePersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();

        if (!$entity instanceof User) {
            return null;
        }

        $this->updateUserPassword($entity);
    }

    public function preUpdate(PreUpdateEventArgs $event)
    {
        $entity = $event->getEntity();

        if (!$entity instanceof User) {
            return null;
        }

        $this->updateUserPassword($entity);
    }

    private function updateUserPassword(User $user)
    {
        $plainPassword = $user->getPlainPassword();

        if (!empty($plainPassword)) {
            $encodedPassword = $this->passwordEncoder->encodePassword($user, $plainPassword);
            $user->setPassword($encodedPassword);
            $user->eraseCredentials();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

令人特别沮丧的是,当自动装配关闭并且我手动编码所有服务时,相同的代码和配置在 Symfony 3 中表现良好。

然而,现在,即使我以通常的方式手动为此编写一个服务条目,仍然没有任何反应。

编辑:

在尝试了 Symfony 文档中 Domagoj 的建议之后,这是我的 services.yaml:

App\Subscriber\UserPasswordChangedSubscriber:
        tags:
            - { name: doctrine.event_subscriber, connection: default }
Run Code Online (Sandbox Code Playgroud)

它不起作用。有趣的是,如果我取消实现 EventSubscriber 接口,Symfony 会抛出异常(正确地)。然而我在代码中的断点被完全忽略了。

我考虑过使用 EntityListener,但它不能有带参数的构造函数,无法访问容器,而且我也不应该这样做;这应该有效:/

Mat*_*Dev 5

我最终弄清楚了这一点。我专门更新的字段是暂时的,因此 Doctrine 不认为这是实体更改(正确地)。

为了解决这个问题,我把

// Set the updatedAt time to trigger the PreUpdate event
$this->updatedAt = new DateTimeImmutable();
Run Code Online (Sandbox Code Playgroud)

在实体字段的 set 方法中,这强制进行更新。

我还需要使用以下代码在 services.yaml 中手动注册订阅者。symfony 4 自动装配对于 Doctrine 事件订阅者来说不够自动。

App\Subscriber\UserPasswordChangedSubscriber:
    tags:
        - { name: doctrine.event_subscriber, connection: default }
Run Code Online (Sandbox Code Playgroud)

  • 如果您的事件订阅者实现“Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface”而不是“Doctrine\Common\EventSubscriber”,那么它将自动连接,无需手动定义服务。 (4认同)