Symfony4服务容器循环依赖

时间:2018-03-29 11:18:24

标签: circular-dependency symfony4

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

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

查看回溯,揭示了一种重复自身的模式,并得出结论 Xdebug 不是应该责备但是两种服务间接依赖于彼此相反。

涉及的服务包括:

  • 日志管理器是一项公共服务,可帮助将用户操作保存到数据库:

    log_manager:
        class: Service\Log\LogManager
        public: true
        arguments:
            - "@doctrine.orm.entity_manager"
            - "@?security.token_storage"
    
  • LoggableSubscriber 使用 LogManager 服务,以便在某些应用程序对象状态发生变化时创建新记录:

    Doctrine\Behavior\ORM\Loggable\LoggableSubscriber:
        public: false
        arguments:
            - "@log_manager"
            - "@event_dispatcher"
        tags:
            - { name: doctrine.event_subscriber }
    

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)
↑↑ ↑↑ ↑↑
…

这纯粹是一个误解问题吗?或者有没有办法通过在配置中的某处设置一些属性/标志来使服务容器意识到这种情况,这样它就不会生气?我看到了几个与此主题相关的问题,但答案是特定于他们的问题的背景。

我打算破坏 LogManager 服务对doctrine实体管理器的依赖,使 LogManager 类无法再将其底层实体对象自身持久化到数据库中,结果通过返回要保留的实例来将该作业委托给调用上下文。我不相信这是理想的解决方案。

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

1 个答案:

答案 0 :(得分:0)

用方法调用替换依赖注入参数确实解决了这个问题。我的log_manager服务定义现在看起来像这样:

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

如果有更好的方法可以解决问题,请发表评论/回答。

相关问题