将EntityManager-dependend服务注入Listener

时间:2015-12-11 15:50:50

标签: symfony event-listener circular-reference symfony-2.7

我正在尝试将我的一个服务注入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

  

检测到服务的循环引用" doctrine.orm.default_entity_manager",路径:" doctrine.orm.default_entity_manager - > doctrine.dbal.default_connection - >听众 - >记录器"

问题显然是我将doctrine注入我的服务,同时它也会自动注入我的监听器。我该怎么办?我找到a very similar question但接受的答案是注入容器,这显然是不利的。

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

小方注意:如果可能的话,我想避免使用lazy services的解决方案。

2 个答案:

答案 0 :(得分:2)

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

  

Doctrine定义了两种可以侦听Doctrine事件的对象:侦听器和订阅者。两者都非常相似,但听众更直接。

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

/** @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();
    // ...

答案 1 :(得分:0)

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

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