Skip to content

Feature Cycle detection

github-actions[bot] edited this page Jul 8, 2026 · 1 revision

🔁 Детекция циклов

← Возможности · Главная · Сравнение

Если A зависит от B, а B — от A, наивный autowiring уходит в бесконечную рекурсию. CloudCastle обнаруживает цикл и бросает понятное исключение вместо зависания.

Принцип работы

Во время autowiring контейнер держит стек разрешаемых id (resolving). Перед сборкой класса он проверяет, нет ли этого id уже в стеке; если есть — это цикл, и бросается ContainerException с цепочкой A → B → A. По завершении сборки id снимается со стека.

// A(B $b) и B(A $a) — циклическая зависимость
$c->enableAutowiring();
$c->get(A::class);
// ContainerException: обнаружена циклическая зависимость A → B → A

⚠️ В сравнительных security-тестах на таком графе Laravel зависает (DoS) — это реальная уязвимость доступности. CloudCastle, PHP-DI, Symfony, Nette цикл детектят.

Плюсы

  • Fail-fast с понятной ошибкой вместо зависания процесса/таймаута.
  • Защита доступности (нет DoS от кривого графа зависимостей).
  • Цепочка в сообщении указывает, где разорвать цикл.

Минусы

  • Детекция — сигнал о проблеме дизайна: цикл нужно устранять, а не «обходить».
  • Небольшая стоимость ведения стека (пренебрежимо мала на фоне рефлексии).

✅ Рекомендуется

  • Разрывать циклы через интерфейсы + lazy / lazyGhost (отложенное создание одной из сторон).
  • Пересматривать дизайн: цикл обычно означает смешение ответственностей.

❌ Антипаттерны

  • Пытаться «победить» цикл setter-инъекцией, оставляя двунаправленную жёсткую связь.
  • Игнорировать исключение и оборачивать в try/catch вместо исправления графа.

Аналоги в других контейнерах

Контейнер Аналог
PHP-DI детекция циклов ✅
Symfony детекция circular reference на компиляции ✅
Laravel нет — уходит в рекурсию/зависание (❌, DoS)
Pimple нет autowiring (—)
Nette детекция на компиляции ✅

CloudCastle, PHP-DI, Symfony, Nette детектят; Laravel — DoS.

См. также: Security-тесты · Lazy service.

Clone this wiki locally