预刷新的循环引用


Circular Reference on preFlush

我的依赖注入遇到了一些麻烦。我试图将记录保存到我的preFlush侦听器中的DB。我通过我自己的服务(自定义日志服务)将此记录保存到DB。我试过这几种方法,但没有一个是工作的,我试过每一个谷歌/堆栈流结果我发现,但没有运气,但我害怕。

这是我的记录器类的设置,所有私有变量都已提交,但设置(我使用请求堆栈和转换器在类的其他地方,不确定我是否应该提交这个问题):

配置:

core.logger:
    class: xxx'CoreBundle'Logger
    arguments: [@request_stack, @doctrine.orm.entity_manager, @translator]
类:

public function __construct(RequestStack $requestStack, EntityManager $em, TranslatorInterface $t)
    {
        $this->requestStack = $requestStack;
        $this->em = $em
        $this->t = $t;
    }
public function addLogEntityChange($uow, $entity) {
        $changeset = $uow->getEntityChangeSet($entity);
        foreach($changeset as $key => $value) {
            $logEntity = new Log();
            //setStuff..
            $this->em->persist($logEntity);
        }
        $this->em->flush();
    }

这里是我的接口代码

配置:

xxxcore.loggerlistener:
  class: xxx'CoreBundle'Listener'LoggerListener
  calls:
    - [ setLogger, [@core.logger] ]
  tags:
    - { name: doctrine.event_listener, event: preFlush }

接口:

    public function setLogger($logger)
    {
        $this->l = $logger;
    }
    public function preFlush(PreFlushEventArgs $args)
    {
        $em = $args->getEntityManager();
        $uow = $em->getUnitOfWork();
        $uow->computeChangeSets();
        foreach ($uow->getScheduledEntityUpdates() as $entity) {
            if($entity instanceof LoggerInterface) {
                $this->l->addLogEntityChange($uow, $entity);
            }
        }
    }

这导致

Circular reference detected for service "doctrine.dbal.xxx_connection", path: "doctrine.dbal.xxx_connection".

我已经尝试手动设置日志记录器类中的实体管理器,因此删除依赖注入并使用setEntityManager函数,但这只是使页面超时。我试过插入service_container,但这也没有真正帮助。

当我持久化一个实体后手动调用函数时,它都可以工作,但我想通过与preFlush侦听器的接口将其自动化。

任何帮助/见解将非常感激!

有意思。这以前出现过:Doctrine onFlush事件侦听器服务的Symfony循环引用异常

在教条标记过程的某个地方,必须有一个编译器传递,将侦听器注入实体管理器并引起循环引用。

我检查了DoctrineBundle代码,是的,实体管理器依赖于它的侦听器,当然,如果侦听器依赖于实体管理器,那么我们得到一个循环引用。

我重复了这个问题:

## services.yml
cerad_project_level_logger:
  class: Cerad'ProjectLevel'LevelLogger
  arguments:
    # - '@doctrine.orm.entity_manager'
cerad_project_level_listener:
  class: Cerad'ProjectLevel'LevelListener
  arguments:
    - '@cerad_project_level_logger'
  tags:
    - { name: doctrine.event_listener, event: preFlush }

解决方法是在logger方法中传递实体管理器,而不是注入它。

    foreach ($uow->getScheduledEntityUpdates() as $entity) {
        if($entity instanceof LoggerInterface) {
            $this->l->addLogEntityChange($em, $uow, $entity);
        }

我很有信心,你的代码仍然不会像预期的那样工作,因为preFlush总是在em->flush之后被调用,你将结束在一个循环中,但至少这将通过循环引用错误。

所有这些问题都将消失,如果你只是做一个记录器实体管理器。此外,您真的想要登录到生产数据库吗?