Skip to content

Feature Composite

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

🔗 Композит/делегирующий контейнер

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

CompositeContainer объединяет несколько PSR-11 контейнеров за единым интерфейсом и ищет сервис по цепочке с фолбэком на следующий контейнер. Аналог Symfony delegate lookup / PHP-DI wrapContainer() — способ собрать приложение из нескольких независимых контейнеров (ядро + сторонний пакет).

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

CompositeContainer реализует Psr\Container\ContainerInterface. В конструктор передаются контейнеры в порядке приоритета (первый — самый приоритетный). get() опрашивает их по порядку и возвращает сервис из первого, у которого has() вернул true; если ни у кого нет — бросает NotFoundException (PSR-11 NotFoundExceptionInterface). has() возвращает true, если сервис есть хотя бы в одном контейнере.

use CloudCastle\DI\Container;
use CloudCastle\DI\CompositeContainer;

$app = new Container();
$app->set('logger', static fn () => new AppLogger());

$vendor = new Container();
$vendor->set('mailer', static fn () => new VendorMailer());

$composite = new CompositeContainer($app, $vendor);

$composite->get('logger'); // из $app
$composite->get('mailer'); // фолбэк на $vendor
$composite->has('unknown'); // false

При совпадении id в нескольких контейнерах выигрывает более ранний — контейнер приложения может переопределить сервис стороннего пакета, просто зарегистрировав тот же id раньше в цепочке.

Плюсы

  • Изоляция графов: приложение и сторонний пакет держат свои определения в отдельных контейнерах, но видны как единый PSR-11.
  • Переопределение по приоритету: ранний контейнер перекрывает поздний без модификации чужого.
  • Чистый PSR-11: композит принимает любой ContainerInterface, не только CloudCastle DI.

Минусы

  • Плоский lookup: композит не связывает графы — сервис из одного контейнера не автовайрит зависимость из другого.
  • Порядок значим: неверная очерёдность даёт «не тот» сервис при совпадении id.

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

  • Подмешивать сторонний PSR-11 контейнер как фолбэк к контейнеру приложения.
  • Собирать модульные приложения, где каждый модуль владеет своим контейнером.

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

  • Заменять композитом нормальную регистрацию в одном контейнере, когда графы связаны зависимостями.
  • Полагаться на порядок как на неявную бизнес-логику вместо явных алиасов/contextual binding.

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

Контейнер Аналог
PHP-DI ContainerBuilder::wrapContainer() — делегирующий контейнер (✅)
Symfony delegate lookup только в legacy interop; штатного композита нет (⚠️)
Laravel нет (❌)
Pimple нет (❌)
Nette нет (❌)

CloudCastle и PHP-DI дают готовый делегирующий контейнер из коробки.

См. также: PSR-11 и базовая регистрация · Алиасы · Contextual binding.

Clone this wiki locally