【问题标题】:Symfony, Doctrine: how to disable Entity Listeners?Symfony,Doctrine:如何禁用实体监听器?
【发布时间】:2019-04-29 07:24:30
【问题描述】:

我需要在不触发特定实体侦听器的情况下使用 Alice Fixtures Bundle 保留一些固定装置。
侦听器通过EntityListeners 注释与我的实体相关联。
我宁愿不改变监听器本身。

我创建了一个可以访问容器的自定义加载器,希望在创建对象之前禁用所有侦听器。

我已经尝试过this answer,但$em->getEventManager()->getListeners() 没有返回实体监听器。

ClassMetadata 为我提供了该实体的订阅实体侦听器列表,但它只是一个只读数组。

有没有办法禁用那些实体监听器?

【问题讨论】:

    标签: symfony doctrine-orm


    【解决方案1】:

    我找到了办法。
    这就是我在加载程序中所做的:

    $em = $this->container->get('doctrine.orm.default_entity_manager');
    
    $entitiesWithListeners = [
        Post::class,
        Comment::class
    ];
    
    $listenersToDisable = [
        MyListener::class
    ];
    
    foreach ($entitiesWithListeners as $entity) {
        $metadata = $em->getMetadataFactory()->getMetadataFor($entity);
    
        foreach ($metadata->entityListeners as $event => $listeners) {
            
            foreach ($listeners as $key => $listener) {
                if (in_array($listener['class'], $listenersToDisable)) {
                    unset($listeners[$key]);
                }
            }
            $metadata->entityListeners[$event] = $listeners;
        }
        $em->getMetadataFactory()->setMetadataFor($entity, $metadata);
    }
    

    我只需获取每个实体的元数据,将其从我的实体侦听器中剥离,然后将其设置回其对应的类。

    这很丑,但是嘿,它有效。 由于我目前坚持使用 AliceBundle v1.4,并且在我们更新项目时我将不得不更改所有内容,这样就可以了。

    【讨论】:

    • 由于 $metadata 是一个对象,并且由于对象在这一行周围的传递方式 $em->getMetadataFactory()->setMetadataFor($entity, $metadata);是多余的。非常感谢您发布此信息,它为我节省了很多时间。
    【解决方案2】:

    您可以使用EntityListenerResolver API

    $em->getConfiguration()->getEntityListenerResolver()->clear();
    

    或者如果你想清除特定类的监听器

    $em->getConfiguration()->getEntityListenerResolver()->clear(YourEntityListener::class);
    

    更多信息请参考EntityListenerResolver接口。

    【讨论】:

    • 当我调用全局clear() 方法时,它似乎确实禁用了一些实体监听器,其中一些我不想禁用。但是当我用我想去掉听众的类的名字来调用它时,它就不起作用了。 ListenersInvoker 仍然从元数据中调用该侦听器。
    • 当然,如果您不传递任何参数,它会清除所有实体侦听器,但您可以传递特定的类来禁用。检查我更新的答案。
    • 抱歉,我正在编辑我的评论。由于某种原因,通过课程没有奏效。我正在调试堆栈,看看我是否理解它是如何工作的......
    • 实际上我看不到 EntityListenerResolver 可能会在哪里发挥作用。例如:在 UnitOfWork::persistNew() 中,唯一决定是否调用侦听器的是 ListenersInvoker,它本身似乎仅依赖于类元数据。 github.com/doctrine/doctrine2/blob/…
    • 哈,正要对此发表评论,但我看到你刚刚更正了这个答案;)是的,它实际上适用于侦听器类的名称。
    猜你喜欢
    • 1970-01-01
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多