【问题标题】:Symfony 4 Doctrine EventSubscriber not usedSymfony 4 Doctrine EventSubscriber 未使用
【发布时间】:2018-07-08 18:28:26
【问题描述】:

尝试注册一个 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 中,当自动装配被关闭并且我手动编码我的所有服务时,相同的代码和配置很好。

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

编辑:

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

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

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

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

【问题讨论】:

  • 请显示所有相关的配置文件。你说了一些关于自动装配和一些关于“手动”配置的东西,但你没有在这里报告相关代码......
  • 目前没有可发布的配置,这是相关的,因为没有任何配置。下面的答案提出了一个我即将尝试的建议(涉及配置)。在自动装配方面,Symfony 3.3 带来了一些关于自动将对象注入类而无需配置(或可选配置)的新变化。现在我要使用默认配置。你可以在这里阅读更多内容symfony.com/doc/current/service_container/3.3-di-changes.html

标签: symfony events doctrine subscriber


【解决方案1】:

我最终想通了。我专门更新的字段是瞬态的,因此 Doctrine 不认为这是实体更改(正确)。

为了解决这个问题,我把

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

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

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

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

【讨论】:

  • 如果您的事件订阅者实现了Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface 而不是Doctrine\Common\EventSubscriber,那么它将自动连接,无需手动定义服务。
【解决方案2】:

对于您的第一个问题,学说事件订阅者没有自动配置/自动标记。原因及解决方法,有一些回复here

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 我已经这样做了,如果你检查问题中的最后一句话:(我可以在 bin/console debug:autowiring 输出中看到它,但看不到标签是否连接为好吧。Symfony 事件文档声称标签是根据它们实现所需接口的概念自动连接的。今晚晚些时候我将再次尝试使用您链接的页面中的确切格式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2018-12-18
    • 2021-12-26
    • 1970-01-01
    • 2018-10-18
    相关资源
    最近更新 更多