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');
抱歉,如果有些地方不太准确,但我对 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');