Symfony4 服务容器循环依赖

Symfony4 service container circular dependency

在使用 symfony-flex 将 symfony3.4 项目迁移到 Symfony4 的过程中...

在调整了目录结构并进行了一些调整之后,我现在面临着一个看起来像 循环依赖性 的错误,它在应用程序服务容器引导阶段出现。点击应用程序(无论是从控制台还是前端)会引发一些与 Xdebug 相关的异常,表示 «已达到嵌套函数调用限制('256')».

查看回溯揭示了一种重复的模式,并得出结论,Xdebug 不是罪魁祸首,而是 两个间接依赖的服务相反,彼此

涉及的服务有:

Backtrace (请从下往上阅读):

==== ↑↑ PATTERN REPEATS ON AND ON ↑↑ ====
==== ONCE AGAIN DOCTRINE LOOKS FOR SUBSCRIBERS ====
at boDevDebugProjectContainer->load('…/var/cache/bo/dev/ContainerTv5AUyL/getLoggableSubscriberService.php')
    in getDoctrine_Dbal_ApiacmeConnectionService.php (line 34)
at require('…/var/cache/bo/dev/ContainerTv5AUyL/getDoctrine_Dbal_ApiacmeConnectionService.php')
    in boDevDebugProjectContainer.php (line 446)
at boDevDebugProjectContainer->load('…/var/cache/bo/dev/ContainerTv5AUyL/getDoctrine_Dbal_ApiacmeConnectionService.php')
    in getDoctrine_Orm_ApiacmeEntityManagerService.php (line 74)
at require('…/var/cache/bo/dev/ContainerTv5AUyL/getDoctrine_Orm_ApiacmeEntityManagerService.php')
    in boDevDebugProjectContainer.php (line 446)
==== "LOGMANAGER" NATURALLY REQUIRES DOCTRINE ENTITY MANAGER SERVICE ====
at boDevDebugProjectContainer->load('…/var/cache/bo/dev/ContainerTv5AUyL/getDoctrine_Orm_ApiacmeEntityManagerService.php')
    in getLogManagerService.php (line 10)
at require('…/var/cache/bo/dev/ContainerTv5AUyL/getLogManagerService.php')
    in boDevDebugProjectContainer.php (line 446)
at boDevDebugProjectContainer->load('…/var/cache/bo/dev/ContainerTv5AUyL/getLogManagerService.php')
    in getLoggableSubscriberService.php (line 11)

==== BUT OUR "LOGGABLESUBSCRIBER" IN TURN NEEDS THE "LOGMANAGER" SERVICE ====
at require('…/var/cache/bo/dev/ContainerTv5AUyL/getLoggableSubscriberService.php')
    in boDevDebugProjectContainer.php (line 446)

==== DOCTRINE LOADS SUBSCRIBERS (ATTACHED VIA "TAG" PROPERTY) ====
at boDevDebugProjectContainer->load('…/var/cache/bo/dev/ContainerTv5AUyL/getLoggableSubscriberService.php')
    in getDoctrine_Dbal_ApiacmeConnectionService.php (line 34)
==== ↑↑ PATTERN STARTS HERE ↑↑ ====

at require('…/var/cache/bo/dev/ContainerTv5AUyL/getDoctrine_Dbal_ApiacmeConnectionService.php')
    in boDevDebugProjectContainer.php (line 446)
at boDevDebugProjectContainer->load('…/var/cache/bo/dev/ContainerTv5AUyL/getDoctrine_Dbal_ApiacmeConnectionService.php')
    in getDoctrine_Orm_ApiacmeEntityManagerService.php (line 74)
at require('…/var/cache/bo/dev/ContainerTv5AUyL/getDoctrine_Orm_ApiacmeEntityManagerService.php')
    in boDevDebugProjectContainer.php (line 446)

==== FIRST, OUR "LOGMANAGER" SERVICE DEPENDS ON DOCTRINE MAIN ENTITYMANAGER ====
at boDevDebugProjectContainer->load('…/var/cache/bo/dev/ContainerTv5AUyL/getDoctrine_Orm_ApiacmeEntityManagerService.php')
    in getLogManagerService.php (line 10)
at require('…/var/cache/bo/dev/ContainerTv5AUyL/getLogManagerService.php')
    in boDevDebugProjectContainer.php (line 446)
↑↑ ↑↑ ↑↑
…

这纯粹是个误会问题吗?或者有没有办法通过在配置中的某处设置一些 property/flag 来让服务容器知道这种情况,这样它就不会发疯? 我看到了几个与这个主题相关的问题,但回答了特定于他们的问题的上下文。

我正要打破 LogManager 服务对 doctrine 实体管理器的依赖,使得 LogManager class 无法持久化它底层实体对象本身不再是数据库,因此通过返回要持久化的实例来将该作业委托给调用上下文。不过,我不认为这是理想的解决方案。

非常感谢建议的方法。
谢谢。

用方法调用替换依赖注入参数确实解决了这个问题。我的 log_manager 服务定义现在如下所示:

log_manager:
    class: Service\Log\LogManager
    public: true
    arguments:
        - "@?security.token_storage"
    calls:
        - ['setEntityManager', ["@doctrine.orm.entity_manager"]]

如果有更好的解决方法请comment/answer