Skip to content

Feature Configuration

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

📄 Декларативная конфигурация (PHP / JSON / YAML / XML)

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

Регистрация сервисов не только кодом, но и декларативными файлами: PHP, JSON, YAML, XML — с загрузкой из каталога и приоритетами. Подробный туториал — Конфигурация, справочник формата — Configuration-reference.

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

ContainerConfigurator читает конфиг через набор лоадеров (PhpConfigurationLoader, JsonConfigurationLoader, YamlConfigurationLoader, XmlConfigurationLoader), нормализует его в определения и применяет к контейнеру. Можно загрузить один файл или каталог — тогда файлы сливаются с учётом приоритета (например, окружение переопределяет базовые настройки).

// services.yaml
services:
  App\Db:
    factory: 'App\DbFactory'
  App\LoggerInterface:
    alias: App\FileLogger

// bootstrap:
$configurator->loadFile(__DIR__ . '/config/services.yaml');
$configurator->loadDirectory(__DIR__ . '/config'); // слияние с приоритетами

YAML требует ext-yaml (опционально; для JSON/PHP/XML не нужен).

Параметры и переменные окружения

Секция parameters + подстановки в значениях (как в Symfony) — разрешаются до применения к контейнеру:

parameters:
  db_host: '%env(DB_HOST:localhost)%'   # env с дефолтом
  db_port: '%env(int:DB_PORT:5432)%'    # типизированный env (int/bool/float/json)
services:
  app.dsn: 'pgsql://%db_host%:%db_port%/app'   # интерполяция параметров
  • %имя% — параметр (целиком → «сырое» значение любого типа; внутри строки → интерполяция);
  • %env(VAR)% / %env(VAR:default)% — переменная окружения (бросает исключение, если не задана и нет дефолта);
  • %env(int:VAR)% / bool / float / json / string — типизированное значение;
  • %% — экранированный процент. Параметры разных слоёв конфига мёржатся (поздний переопределяет).

Setter-инъекция (calls)

Ключ calls вызывает методы сервиса после конструирования — декларативный аналог Symfony calls:. Каждая запись — имя метода либо [метод, [аргументы]]; применяется к каждому новому экземпляру.

// PHP / YAML / JSON
'services' => [
    'app.report' => [
        'class' => App\Report::class,
        'calls' => [
            ['setPrefix', ['app_']],      // литерал (можно %параметр% / %env(...)%)
            ['setLogger', ['@logger']],   // '@id' — ссылка на другой сервис
            ['enable'],                   // метод без аргументов
        ],
    ],
],
  • Аргумент @id — ссылка на сервис ($c->get('id')); @@ в начале строки — экранированный литерал @.
  • Строковые ключи в списке аргументов передаются как именованные параметры метода.
  • Некорректная запись (без имени метода) — ошибка на этапе применения конфига; несуществующий метод — при резолве. Поддержано в PHP/YAML/JSON.

Сервис-фабрики (factory)

Ключ factory создаёт сервис вызовом метода — экземпляра другого сервиса или статического метода класса (аналог Symfony factory:):

'services' => [
    // фабрика-экземпляр: вызвать метод сервиса '@app.factory'
    'app.report' => [
        'factory'   => ['@app.factory', 'createReport'],
        'arguments' => ['%report.type%', '@app.clock'],
    ],
    // статическая фабрика: Class::method(...)
    'app.uuid' => ['factory' => [Ramsey\Uuid\Uuid::class, 'uuid4']],
    // строковая форма статической фабрики
    'app.now'  => ['factory' => 'App\Clock::now'],
],
  • ['@id', 'method'] — метод сервиса-экземпляра; ['Class', 'method'] или 'Class::method' — статический метод.
  • arguments разрешаются как у calls: литералы, %параметры%/%env%, ссылки @id, именованные ключи.
  • Некорректный factory — ошибка при применении конфига; несуществующий метод — при резолве.

Наследование определений (parent / abstract)

Общую часть определений можно вынести в шаблон и переиспользовать (аналог Symfony parent:/abstract:):

'services' => [
    // шаблон: сам сервисом не регистрируется
    '_repository' => [
        'abstract' => true,
        'class'    => App\BaseRepository::class,
        'calls'    => [['setConnection', ['@db']]],
    ],
    'user.repository' => [
        'parent' => '_repository',                 // наследует class + calls
        'calls'  => [['setTable', ['users']]],     // добавляется к calls родителя
    ],
],
  • parent: 'id' — потомок получает ключи родителя; одноимённые скалярные ключи (class, factory, lazy) потомок переопределяет, список calls дополняется (сначала родительские, затем потомка).
  • abstract: true — определение-шаблон, самим сервисом не регистрируется (has()false).
  • Неизвестный parent — ошибка при применении конфига. Рекомендуется помечать шаблоны abstract, чтобы их calls не применялись к другим сервисам того же класса.

Устаревшие сервисы (deprecated)

Ключ deprecated помечает сервис устаревшим: при создании нового экземпляра эмитится E_USER_DEPRECATED (аналог Symfony deprecated:):

'services' => [
    'legacy.mailer' => [
        'class'      => App\LegacyMailer::class,
        'deprecated' => 'Используйте App\Mailer вместо legacy.mailer.',
    ],
    'old.repo' => ['class' => App\OldRepo::class, 'deprecated' => true], // сообщение по умолчанию
],
  • deprecated: 'сообщение' — своё сообщение; deprecated: true — сообщение по умолчанию; false/отсутствие — без пометки.
  • Предупреждение эмитится через хук before-resolving перед созданием нового экземпляра (для singleton — при первом обращении).

Условные по окружению определения (when)

Секция when задаёт переопределения по имени окружения; активное окружение — в ключе environment (обычно %env(APP_ENV)%). Совпавшие переопределения сливаются поверх базовой конфигурации (аналог Symfony when@env):

'environment' => '%env(APP_ENV:prod)%',
'services' => [
    'mailer' => ['class' => App\SmtpMailer::class],   // база (prod)
],
'when' => [
    'dev'  => ['services' => ['mailer' => ['class' => App\NullMailer::class]]],
    'test' => ['services' => ['mailer' => ['class' => App\ArrayMailer::class]]],
],
  • Переопределения мёржатся по секциям: сервисы/alias'ы с тем же id заменяются, новые — добавляются; несуществующие в базе секции добавляются целиком.
  • Если environment не задан или нет ветки when.<environment> — применяется только база.

Валидация схемы

Перед применением конфигурация проверяется (fail-fast): неизвестная секция верхнего уровня (например, опечатка servcies вместо services) сразу бросает ContainerException с перечнем допустимых секций — типичный «молчаливый» баг не проходит незаметно.

По умолчанию типы значений известных секций обрабатываются мягко (устойчивое слияние слоёв). Чтобы включить строгую проверку типов, добавьте ключ strict: true в конфигурацию — тогда неверный тип любой секции тоже отклоняется fail-fast: services / parameters / aliases / bind / tags / autowire / scan / contextual / register_attributes / autowiring / when обязаны быть массивами, environment — строкой, priority — целым.

# services.yaml
strict: true              # включить строгую проверку типов секций
services:
  App\Db: { factory: 'App\DbFactory' }
# services: 'oops'  →  ContainerException: секция "services" должна быть типа "array"

Строгий режим — opt-in: без ключа strict поведение полностью совместимо с прежним.

Плюсы

  • Единый обзор графа в файлах — удобно для больших приложений и не-программистов.
  • Разделение окружений через каталог + приоритеты (base → prod/test override).
  • Четыре формата на выбор — под привычки команды (в отличие от контейнеров с одним форматом).

Минусы

  • Декларативный конфиг многословнее autowiring для простых классов.
  • YAML/XML — дополнительный слой парсинга (стоимость на старте; в проде — compiled).

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

  • Хранить в конфиге то, что меняется по окружению (DSN, ключи, реализации), остальное отдавать autowiring.
  • Разбивать на каталог: config/services/*.yaml + окружение поверх.
  • Не класть секреты в конфиг — только ссылки на защищённое хранилище/ENV.

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

  • Описывать в конфиге весь тривиальный граф, дублируя то, что решает autowiring.
  • Смешивать бизнес-данные и определения сервисов в одном файле.

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

Контейнер Аналог
PHP-DI PHP-массивы; JSON/YAML — ограниченно (⚠️)
Symfony YAML / XML / PHP — эталонная система конфигов
Laravel PHP service providers; декларативных файлов сервисов нет (⚠️)
Pimple нет (❌ — только код)
Nette NEON (свой формат)

CloudCastle, Symfony, Nette — богатая декларативная конфигурация; CloudCastle покрывает PHP/JSON/YAML/XML.

См. также: Конфигурация (гайд) · Справочник конфигурации · Сканирование каталога.

Clone this wiki locally