Symfony 4 Doctrine EventSubscriber not used

狂风中的少年 提交于 2019-12-24 15:56:50

问题


Trying to register a Doctrine EventSubscriber but nothing is ever actually fired.

I have, on the Entity, in question, set the @ORM\HasLifeCycleCallbacks annotation.

Here's the Subscriber:

<?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();
        }
    }
}

The part that is making this particuarly frustrating is that this same code and configuration was fine in Symfony 3 whe autowiring was turned off and I manually coded all my services.

However, now, even if I manually code up a service entry for this, in the usual way, still nothing happens.

EDIT:

Here is my services.yaml after trying what suggested Domagoj from the Symfony docs:

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

It didn't work. Interestingly, If I un-implement the EventSubscriber interface, Symfony throws an exception (rightly). Yet my break points in the code are completely ignored.

I've considered an EntityListener, but it cannot have a constructor with arguments, doesn't have access to the Container and I shouldn't have to; this ought to work :/


回答1:


I ended up figuring this out. The field that I was specifically updating was transient, and therefore Doctrine didn't consider this an Entity change (rightly).

To fix this, I put

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

In the Entity field's set method and this forced an update.

I also did need to manually register the Subscriber in the services.yaml using the following code. symfony 4 autowiring wasn't auto enough for a Doctrine Event Subscriber.

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



回答2:


You have to register your Event Listener as a service and tag it as doctrine.event_listener

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




回答3:


For your first problem, doctrine event subscribers are not autoconfigured/auto-tagged. For the reasons and solutions, you have some responses here.

Personnaly, I just have one Doctrine ORM mapper, so I put this in my services.yaml file :

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


来源:https://stackoverflow.com/questions/51234927/symfony-4-doctrine-eventsubscriber-not-used

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!