Новое в Symfony 5.1: Абстрактные сервисные аргументы

Иногда при определении служб в ваших приложениях Symfony есть аргументы, которые нельзя добавить в конфигурационные файлы. Причина заключается в том, что их значения могут быть рассчитаны только во время выполнения на этапе компиляции или расширения пакета.

В этих случаях обычно добавляют пустой аргумент с некоторым комментарием, объясняющим, что значение будет введено позже. Например, вторым аргументом этого сервиса является полный список каталогов, в которых хранятся шаблоны Twig. Этот список доступен только при запуске приложения, поскольку пакеты могут также добавлять свои собственные каталоги:

<service id="twig.template_iterator" class="Symfony\Bundle\TwigBundle\TemplateIterator">
    <argument type="service" id="kernel" />
    <argument type="collection" /> <!-- Twig paths -->
    <argument>%twig.default_path%</argument>
</service>

Этому другому сервису необходимо корневое пространство имен приложения, которое лучше рассчитать динамически при запуске приложения (вместо того, чтобы заставлять пользователя настраивать это значение вручную):

<service id="maker.generator" class="Symfony\Bundle\MakerBundle\Generator">
    <argument type="service" id="maker.file_manager" />
    <argument /> <!-- root namespace -->
</service>

В Symfony 5.1 улучшили этот конфиг, чтобы заменить «пустой аргумент + комментарий» на надлежащие абстрактные аргументы сервиса. Это аргументы, значения которых могут быть вычислены только во время выполнения в проходах компилятора или расширениях пакета.

Вот как выглядит предыдущий пример при использовании абстрактных аргументов:

<service id="maker.generator" class="Symfony\Bundle\MakerBundle\Generator">
    <argument type="service" id="maker.file_manager" />
    <argument type="abstract" key="$rootNamespace">defined in MakerPass</argument>
</service>

Значение ключа определяет имя аргумента в конструкторе службы, а значение, заключенное в <argument> ... </argument>, является необязательным комментарием к аргументу. Если вы используете YAML для определения сервисов, используйте этот другой синтаксис на основе ключевого слова! abstract:

maker.generator:
    class: Symfony\Bundle\MakerBundle\Generator
    arguments:
        $rootNamespace: !abstract defined in MakerPass

Это конфигурация, необходимая при использовании PHP:

use Symfony\Bundle\MakerBundle\Generator;
use Symfony\Component\DependencyInjection\Argument\AbstractArgument;

$builder->register('maker.generator', Generator::class)
    ->setArgument('$rootNamespace', new AbstractArgument('defined in MakerPass'));

Если вы не замените значение абстрактных аргументов в каком-либо проходе компилятора или расширении пакета, вы увидите следующее сообщение об ошибке:

Аргумент “$rootNamespace” службы “maker.generator” является абстрактным (определен в MakerPass), вы забыли его определить?