未使用 Symfony 4 Doctrine EventSubscriber

Symfony 4 Doctrine EventSubscriber not used

正在尝试注册一个 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();
        }
    }
}

让这件事特别令人沮丧的部分是,当自动装配被关闭并且我手动编码我的所有服务时,相同的代码和配置在 Symfony 3 中很好。

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

编辑:

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

App\Subscriber\UserPasswordChangedSubscriber:
        tags:
            - { name: doctrine.event_subscriber, connection: default }

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

我考虑过 EntityListener,但它不能有带参数的构造函数,不能访问 Container,我不应该这样做;这应该有效:/

您必须将事件侦听器注册为服务并将其标记为 doctrine.event_listener

https://symfony.com/doc/current/doctrine/event_listeners_subscribers.html#configuring-the-listener-subscriber

我终于弄明白了。我专门更新的字段是暂时的,因此 Doctrine 不认为这是实体更改(正确)。

为了解决这个问题,我输入了

// Set the updatedAt time to trigger the PreUpdate event
$this->updatedAt = new DateTimeImmutable();

在实体字段的设置方法中,这强制更新了。

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

App\Subscriber\UserPasswordChangedSubscriber:
    tags:
        - { name: doctrine.event_subscriber, connection: default }

对于您的第一个问题,学说事件订阅者不是 autoconfigured/auto-tagged。原因及解决办法,大家有一些回应here.

Personnaly,我只有一个 Doctrine ORM 映射器,所以我把它放在我的 services.yaml 文件中:

services:
    _instanceof:
        Doctrine\Common\EventSubscriber:
            tags: ['doctrine.event_subscriber']