将依赖于 EntityManager 的服务注入 Listener

Injecting EntityManager-dependend service into Listener

我正在尝试将我的一项服务注入 EntityListener,以便在实体更新时调用某些特定于应用程序的行为。

我的 Logger 服务,用于在我的数据库中的 LogEntry 实体中存储事件:

class Logger
{
    /**
     * @var EntityManager $manager The doctrine2 manager
     */
   protected $manager;
   //...
}

听众:

class EntityListener
{
    public function __construct(Logger $logger)
    {
        $this->logger = $logger;
         // ...
    }
}

以及我的 service.yml 中的服务定义:

listener:
    class: Namespace\EntityListener
    arguments: [@logger]
    tags:
        - { name: doctrine.event_listener, event: preUpdate }

logger:
    class: Namespace\Logger
    arguments: [@doctrine.orm.entity_manager]

不幸的是,它导致 ServiceCircularReferenceException:

Circular reference detected for service "doctrine.orm.default_entity_manager", path: "doctrine.orm.default_entity_manager -> doctrine.dbal.default_connection -> listener -> logger".

问题显然是我将 doctrine 注入到我的服务中,同时它也自动注入到我的侦听器中。我该如何进行?我找到了 a very similar question 但公认的答案是 注入容器 这显然是不利的。

任何关于如何解决我的问题的建议都将不胜感激。


小提示:如果可能的话,我想避免依赖 lazy services 的解决方案。

首先,我从 EventListener 切换到 EventSubscriber。来自 docs:

Doctrine defines two types of objects that can listen to Doctrine events: listeners and subscribers. Both are very similar, but listeners are a bit more straightforward.

事实证明,可以通过传递的 $args 参数访问 ObjectManager,如下所示:

/** @var Doctrine\Common\Persistence\ObjectManager $manager */
$manager = $args->getObjectManager();

所以要么直接在回调中使用它:

public function postUpdate(LifecycleEventArgs $args)
{
    $manager = $args->getObjectManager();
    // ...

...或将其设置为对象字段:

/** @var ObjectManager $manager */
private $manager;

public function postUpdate(LifecycleEventArgs $args)
{
    $this->manager = $args->getObjectManager();
    // ...

在遇到同样的问题后,我发现使用延迟加载解决了我的问题。

listener:
    class: AppBundle\EventListener\OrderDoctrineListener
    tags:
        - { name: doctrine.event_listener, event: postPersist, lazy: true }