Doctrine 事件侦听器“...”必须指定 "event" 属性

Doctrine event listener "..." must specify the "event" attribute

我想在将 User 对象持久化到数据库之前注册 Doctrine 事件侦听器以散列用户密码:

这是我的事件监听器class:

<?php

namespace AppBundle\Doctrine;

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

class HashPasswordListener implements EventSubscriber
{
    private $passwordEncoder;

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

    public function getSubscribedEvents()
    {
        return ['prePersist', 'preUpdate'];
    }

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

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

        $this->encodePassword($entity);
    }

    /**
     * @param User $entity
     */
    private function encodePassword(User $entity)
    {
        $encoded = $this->passwordEncoder->encodePassword($entity, $entity->getPlainPassword());
        $entity->setPassword($encoded);
    }

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

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

        $this->encodePassword($entity);
    }
}

然后我在 services.yml 文件中注册了这个事件监听器

    AppBundle\Doctrine\HashPasswordListener:
    tags: ['doctrine.event_listener']

但是每当我想通过加载固定装置数据或从 Web 应用程序插入用户时,我都会收到这样的错误:

[Symfony\Component\DependencyInjection\Exception\InvalidArgumentException]
  Doctrine event listener "AppBundle\Doctrine\HashPasswordListener" must specify the "event" attribute.

我尝试在 tags 中添加事件属性,但也没有用。

我正在使用 Symfony 3.3 版和 Doctrine 2.5

config.yml 中配置了 Doctrine,所以:

doctrine:
dbal:
    driver: pdo_sqlite
    path: '%kernel.project_dir%/app/sqlite.db'
    charset: UTF8

错在哪里?

您需要在 services.yml 文件中为该事件侦听器配置事件属性。它不起作用 w/o,这就是您看到错误消息的原因。

有关完整示例,请参阅

您使用 un subscriber,因此您必须标记 doctrine event subscriber 而不是需要属性事件的事件侦听器。

AppBundle\Doctrine\HashPasswordListener:
标签: ['doctrine.event_subscriber']

我想通了。我应该在 service.yml 中配置事件侦听器,所以:

AppBundle\Doctrine\HashPasswordListener:
        tags:
            - { name: doctrine.event_listener, event: prePersist }
            - { name: doctrine.event_listener, event: preUpdate }

效果很好。

您还可以在实体中添加一个 EventListener

/**
 * @ORM\Entity(repositoryClass=XXXX::class)
 * @ORM\HasLifecycleCallbacks() NEED IT !
 * @ORM\EntityListeners({"App\EventListener\XXXXListener"})
*/
class XXX

然后在你的 EventListener 中:

class XXXListener
{
    public function preUpdate(XXX $xxx, PreUpdateEventArgs $event): void
    {
        $xxx->setDateUpdate(new DateTime());
    }
}

文档:https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#entity-listeners