php - 关于 preFlush 的循环引用

标签 php symfony circular-reference

我在依赖注入(inject)方面遇到了一些问题。我正在尝试将记录保存到 preFlush 监听器中的数据库中。我通过我自己的服务(自定义日志记录服务)将此记录保存到数据库中。我已经尝试了几种方法,但没有一个有效,我已经尝试了我找到的所有 google/stackover flow 结果,但恐怕还没有运气。

这是我的记录器类的设置,所有私有(private)变量都已省略但已设置(我在类中的其他位置使用请求堆栈和翻译器,不确定我是否应该省略这个问题):

配置:

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

类(class):

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".

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

在持久化实体后手动调用函数时,一切正常,但我想通过带有 preFlush 监听器的接口(interface)自动执行此操作。

任何帮助/见解将不胜感激!

最佳答案

有趣。这之前已经出现过:Symfony Circular Reference Exception for Doctrine onFlush Event Listener Service

在教条标记过程中的某个地方,必须有一个编译器 channel 将监听器注入(inject)到实体管理器中并导致循环引用。

我检查了 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 }

解决方法是在记录器方法中传递实体管理器,而不是注入(inject)它。

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

我相当有信心您的代码仍然无法按预期工作,因为 preFlush 总是在 em->flush 之后调用,并且您最终会陷入循环,但至少这会克服循环引用错误。

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

关于php - 关于 preFlush 的循环引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33282325/

相关文章:

php - 如何使用 nl2br 删除\n和添加中断

php - 获取数据,处理付款,然后再获取

php - MYSQL/PDO PHP系统---寻找大笔画输入

php - Symfony:定义作用域 HttpClient 类

php - 仅当子对象尚不存在时才将子对象添加到父对象

python - 重新加载时无法访问gc()

c# - 什么是循环引用销毁序列

types - 如何在 TypeScript 中创建循环引用类型?

php - 为什么在 PHP 中连接到 MySQL 大约需要 2 秒?

php - 在 Doctrine 中使用设置为 NULL 的唯一 ID 创建的实体对象