Циклическая зависимость сервисного контейнера Symfony4

В процессе миграции проекта symfony3.4 на Symfony4 с помощью symfony-flex

После адаптации структуры каталогов и выполнения нескольких корректировок я теперь сталкиваюсь с тем, что выглядит как ошибка круговая зависимость, которая обнаруживается на этапе начальной загрузки контейнера службы приложений. Нажатие на приложение (с консоли или с внешнего интерфейса) вызывает некоторое исключение, связанное с 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 }
    

Обратная трассировка(пожалуйста, прочтите снизу вверх):

==== ↑↑ 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 от диспетчера сущностей доктрины, в результате чего класс LogManager больше не мог сохранять свой базовый объект сущности в базе данных сам по себе и, как следствие, делегировал это задание вызывающему контексту, возвращая вместо этого экземпляр для сохранения. Я не уверен, что это идеальное решение.

Предлагаемый подход был бы очень признателен. Спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
408
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Замена аргумента внедрение зависимости на вызов метода устранила проблему. Мое определение службы log_manager теперь выглядит так:

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

Прокомментируйте / ответьте, если есть лучший способ решить проблему.

Другие вопросы по теме