-
-
Notifications
You must be signed in to change notification settings - Fork 1
Compiled container
Compiled container (v1.9.0, #24) — генерация PHP-класса wiring из замороженного runtime-контейнера. На hot path get() нет reflection: создание сервисов — через match и готовые PHP-выражения.
| Сценарий | Runtime Container
|
Compiled |
|---|---|---|
| Разработка, частые правки wiring | ✅ | ❌ |
Production, сотни/тысячи get()
|
✅ | |
| CI/deploy с фиксированным графом | ✅ + freeze()
|
✅ compile в build-step |
Фабрики set('id', fn () => …)
|
✅ | ❌ |
| Property / method injection | ✅ | ❌ (только constructor) |
<?php
declare(strict_types=1);
use CloudCastle\DI\Compiler\ContainerCompiler;
use CloudCastle\DI\Container;
require __DIR__ . '/vendor/autoload.php';
// 1. Собрать граф в dev / build-скрипте
$container = new Container();
$container->autowire(App\Service\OrderService::class);
$container->bind(LoggerInterface::class, FileLogger::class);
$container->tag(FileLogger::class, 'loggers');
$container->freeze();
// 2. Скомпилировать в PHP-файл
$result = (new ContainerCompiler())->compile(
$container,
__DIR__ . '/var/compiled/AppContainer.php',
AppContainer::class, // FQCN; null → из имени файла
);
// $result->className, $result->outputPathВ production подключайте сгенерированный класс:
require __DIR__ . '/var/compiled/AppContainer.php';
/** @var \CloudCastle\DI\Contract\CompiledContainerInterface $container */
$container = new AppContainer();
$order = $container->get(OrderService::class);flowchart LR
subgraph bootstrap [Bootstrap]
C[Container]
F[freeze]
end
subgraph compile [Build step]
SB[ContainerCompileSnapshotBuilder]
GEN[CompiledContainerPhpGenerator]
PHP[AppContainer.php]
end
subgraph runtime [Production]
AC[AbstractCompiledContainer]
GET[get без reflection]
end
C --> F
F --> SB
SB --> GEN
GEN --> PHP
PHP --> AC
AC --> GET
| Возможность | Поддержка |
|---|---|
set($id, scalar / array / null) |
✅ Literal |
set($id, new Foo()) без параметров конструктора |
✅ NewInstance |
autowire(FQCN) — constructor autowiring |
✅ Autowired |
bind() + autowire()
|
✅ |
alias() |
✅ |
tag(), getTagged*()
|
✅ (теги в snapshot) |
Attributes Inject / Autowire на параметрах конструктора
|
✅ |
Autowiring по имени параметра (enableParameterNameAutowiring) |
✅ |
| Union / intersection в конструкторе | ✅ (как в runtime) |
get(), has(), make(), call()
|
✅ (compiled immutable + frozen) |
dump(), getDefinitionIds()
|
✅ |
Компилятор бросает ContainerCompileException, если:
| Условие | Причина |
|---|---|
Контейнер не freeze()
|
Снимок должен быть стабильным |
set('id', fn (): …) — callable-фабрика |
Нет runtime-вызова фабрик |
enableAutowiring() (глобальный autowiring) |
Только явный autowire() по классам |
enablePropertyAutowiring() / enableMethodAutowiring()
|
Только constructor injection |
decorate() |
Декораторы не в snapshot |
afterResolving() |
Hooks не переносятся |
| Property / method attributes inject | Только constructor |
set($id, new Foo($dep)) — объект с аргументами конструктора |
Используйте autowire()
|
Contextual binding (#25) — да с v1.13.0: правила bake-in в конструктор и contextualGive(); when() на compiled-контейнере недоступен.
public function compile(
ContainerInterface $container,
string $outputPath,
?string $className = null,
): ContainerCompileResult;| Параметр | Описание |
|---|---|
$container |
Только CloudCastle\DI\Container
|
$outputPath |
Путь к .php; каталог создаётся при необходимости |
$className |
FQCN; при null — CloudCastle\DI\Compiled\{Basename}
|
| Поле | Тип | Описание |
|---|---|---|
className |
string |
FQCN сгенерированного класса |
outputPath |
string |
Записанный файл |
Расширяет ContainerInterface, добавляет getCompiledClassName(): string. Сгенерированный класс extends AbstractCompiledContainer — изменение определений после создания запрещено (assertImmutable).
# composer.json scripts (пример)
php tools/compile-container.php<?php
// tools/compile-container.php — пример build-скрипта
declare(strict_types=1);
use CloudCastle\DI\Compiler\ContainerCompiler;
use CloudCastle\DI\Container;
require __DIR__ . '/../vendor/autoload.php';
$container = require __DIR__ . '/../bootstrap/container.php';
(new ContainerCompiler())->compile(
$container,
__DIR__ . '/../var/compiled/AppContainer.php',
);Добавьте var/compiled/ в autoload (composer classmap или PSR-4) или require в bootstrap.
Интеграционные тесты (CompiledContainerIntegrationTest) проверяют, что compiled-контейнер даёт те же экземпляры и теги, что runtime на момент freeze().
-
Bootstrap — composition root и
freeze() - API-reference
- Сравнение — compiled vs PHP-DI / Symfony
- Upgrading — миграция 1.8 → 1.9
-
Testing —
tests/Unit/Compiler/,tests/Integration/CompiledContainerIntegrationTest.php
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
- 📋 Справочник API
- 🏭 Фабрики и singleton