-
-
Notifications
You must be signed in to change notification settings - Fork 1
Feature PSR11
Стандартный контракт доступа к сервисам: get(string $id) и has(string $id) из PSR-11, плюс явная регистрация set().
Container реализует Psr\Container\ContainerInterface. Регистрация складывает определение (экземпляр, скаляр или фабрику) в карту definitions по строковому id. Первый get($id) разрешает определение (вызывает фабрику или возвращает значение), кэширует результат в resolved и возвращает его; повторный get($id) отдаёт тот же объект одним хеш-lookup (hot path). has($id) проверяет наличие без создания экземпляра.
use CloudCastle\DI\Container;
$c = new Container();
$c->set('db.dsn', 'pgsql://localhost/app'); // скаляр
$c->set(Logger::class, fn () => new Logger('/var/log')); // фабрика
$c->has('db.dsn'); // true — без создания
$c->get(Logger::class); // Logger (создан и закэширован)
$c->get(Logger::class); // тот же экземплярПри отсутствии id get() бросает NotFoundException (реализует Psr\Container\NotFoundExceptionInterface), при ошибке создания — ContainerException (ContainerExceptionInterface).
-
Совместимость. Любой код, ожидающий
Psr\Container\ContainerInterface, работает с CloudCastle без адаптеров. -
Предсказуемость.
set()явно фиксирует, что и как создаётся — без «магии» скрытых провайдеров. -
Быстрый
get()из кэша — прямой возврат без alias-резолва и проверок (см. Производительность). -
Честный
has()— не инстанцирует сервис ради проверки (в отличие от контейнеров, гдеhas()= «попробовать создать»).
- Строковые id не типобезопасны — опечатка ловится только в рантайме (митигируется использованием
Class::classкак id). - Явная регистрация многословнее, чем чистый autowiring, — для больших графов включайте autowiring.
- Использовать
Class::class/Interface::classкак id — рефакторинг-safe и совместимо с autowiring. - Регистрировать фабрики как
callable, а не готовые объекты, — экземпляр создаётся лениво при первомget(). - Проверять наличие через
has()передget()в опциональных сценариях.
-
Service Locator по всему коду: прокидывать сам контейнер в сервисы и дёргать
get()внутри бизнес-логики. Внедряйте зависимости через конструктор — контейнер собирает граф на границе (composition root). См. Анти-паттерны. - Хранить в контейнере изменяемое состояние запроса под общими id (см. Scoped-сервисы).
| Контейнер | Аналог |
|---|---|
| PHP-DI |
get() / has() (PSR-11); has() может пытаться разрешить autowiring |
| Symfony | PSR-11 get() / has(); регистрация — через services.yaml / ContainerBuilder
|
| Laravel |
make() / bound(); PSR-11 адаптер есть, но has() неоднозначен |
| Pimple |
$c['id'] (ArrayAccess); PSR-11 — только через Pimple\Psr11\Container (🔌) |
| Nette | PSR-11 через адаптер; нативно — getByType() / getService()
|
CloudCastle, Symfony, Nette — чистый has() без создания.
См. также: Фабрики и singleton · Справочник API.
CloudCastle DI · · PHP 8.1+ · PSR-11
GitHub · Packagist · Releases · Discussions · Сравнение
Исходники Wiki — каталог wiki/ в репозитории (синхронизация через GitHub Actions)
- 🏗️ Архитектура
- ⚡ Быстрый старт
- 📊 Сравнение — 5 аналогов, таблица + победители
- 🧩 Возможности (детально) — каждая фича: принцип, +/−, аналоги
- 🧪 Bootstrap
- 🚀 Compiled container
- 🔗 Contextual binding
- 🤖 Autowiring
- 📄 Конфигурация
- 📖 Справочник конфигурации
- 📂 Сканирование классов
- 🌍 Глобальный реестр
- 🏷️ Теги и декораторы
- 🔗 call(), bind(), hooks
- 🔄 Прототипы, alias, lazy, lazyGhost
- 📋 Справочник API
- 🏭 Фабрики и singleton