Symfony 似乎注册了,但没有触发我的学说事件

Symfony seems to register, but not trigger my doctrine event

抱歉,如果有些地方不太准确,但我对 Symfony 经验不足

我有以下 orm 映射:

src/app/ExampleBundle/Resources/config/doctrine/Base.orm.yml

app\ExampleBundle\Entity\Base:
type: mappedSuperclass
fields:
    createdAt:
        type: datetime
        nullable: true
        options:
            default: null
    updatedAt:
        type: datetime
        nullable: true
        options:
            default: null

这创建了一个我修改为抽象的实体 Base

src/app/ExampleBundle/Entity/Base.php

abstract class Base {
    ...
}

我有一些其他实体,它们扩展了这个摘要class例如

src/app/ExampleBundle/Entity/Category.php

class Category extends Base
{
    ...
}

现在我尝试添加一个侦听器,为每个扩展基础实体的实体 createdAt/updatedAt 设置 createdAt/updatedAt 日期时间

src/app/ExampleBundle/EventListener/BaseListener.php

namespace app\ExampleBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\User\UserInterface;
use app\ExampleBundle\Entity\Base;

class BaseListener
{
    protected $tokenStorage;

    public function __construct(TokenStorage $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    public function prePersist(Base $base, LifecycleEventArgs $event)
    {
        $user = $this->tokenStorage->getToken()->getUser();
        if (!$user instanceof UserInterface) {
            $user = null;
        }

        if ($base->getCreatedAt() === null) {
            $base->setCreated($user, new \DateTime());
        } else {
            $base->setUpdated($user, new \DateTime());
        }
    }
}

并将其添加到捆绑包中 services.yml

src/app/ExampleBundle/Resources/config

services:
    app\ExampleBundle\EventListener\BaseListener:
        arguments: ['@security.token_storage']
        tags:
            - { name: doctrine.orm.entity_listener, entity: app\ExampleBundle\Entity\Base, event: prePersist }

Symfony 没有抛出异常,但定义的事件似乎也没有触发。

我尝试将服务中的实体参数更改为 "real" 实体类别,但仍然没有错误,也没有触发事件。

我想,我按照文档中的描述做了一切。但是还是不行。

命令

debug:event-dispatcher

也不显示事件

所以,问题是:我做错了什么?

这是我遵循的文档https://symfony.com/doc/3.4/doctrine/event_listeners_subscribers.html

为所有实体调用 prePersist 方法,因此您必须排除 app\ExampleBundle\Entity\Base 的非实例。第一个参数是 LifecycleEventArgs。

public function prePersist(LifecycleEventArgs $event)
{
    $base = $event->getObject();
    if (!$base instanceof Base) {
        return;
    }
    $user = $this->tokenStorage->getToken()->getUser();
    if (!$user instanceof UserInterface) {
        $user = null;
    }

    if ($base->getCreatedAt() === null) {
        $base->setCreated($user, new \DateTime());
    } else {
        $base->setUpdated($user, new \DateTime());
    }
}

我可以推荐你StofDoctrineExtensionsBundle (Timestampable) that does exactly what you want. It based on DoctrineExtensions

甚至还有一个 trait 非常有用。

经过一些研究,更多的测试,深入到 EntityManager 和 UnitOfWork。似乎没有什么工作正常。到目前为止,我可以在 doctrine:fixtures:load 上工作,但出于任何原因,如果我在控制器中使用实体管理器,它们仍然无法工作。所以,我决定尝试另一种方式与订阅者。

tags:
    - { name: doctrine.event_subscriber }

class ... implements EventSubscriber

所以我仍然不知道为什么 Listener 没有按预期工作,但是通过订阅者我找到了一个解决方案。

感谢大家的支持:)

对于 Symfony 5 和任何在 Events::loadClassMetadata 未在订阅者中被解雇时遇到问题的人。

Class 应该实现“EventSubscriberInterface”

class DiscriminatorSubscriber implements EventSubscriberInterface
{

public function getSubscribedEvents()
{
    return [Events::loadClassMetadata];
}

public function loadClassMetadata(LoadClassMetadataEventArgs $event): void
{

}

如果您在 services.yml

中将自动配置和自动装配设置为 TRUE,那么您就不必再做任何事情了

Doctrine 将处理您的订阅者注册(检查 DoctrineExtension.php)

 $container->registerForAutoconfiguration(EventSubscriberInterface::class)
        ->addTag('doctrine.event_subscriber');