Symfony News

New in Symfony 5.1: Abstract service arguments

Islam Israfilov

Contributed by
Islam Israfilov
in #35076.

Sometimes, when defining services in your Symfony applications, there are arguments that can't be added in config files. The reason is that their values can only be calculated at runtime in a compiler pass or bundle extension.

In those cases, it's common to add an empty argument with some comment explaining that the value will be injected later. For example, the second argument of this service is the full list of directories where Twig templates are stored. That list is only available when running the application, because bundles can add their own directories too:

1
2
3
4
5
<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>

This other service needs the root namespace of the application, something that's better to calculate dynamically when running the application (instead of forcing the user to configure this value manually):

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

In Symfony 5.1 we've improved this config to replace the "empty argument + comment" by proper abstract service arguments. These are arguments whose values can only be calculated at runtime in compiler passes or bundle extensions.

This is how the previous example looks like when using abstract arguments:

1
2
3
4
<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>

The key value defines the argument name in the service constructor and the value enclosed in <argument> ... </argument> is an optional comment about the argument. If you use YAML to define services, use this other syntax based on the !abstract keyword:

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

If you don't replace the value of the abstract arguments in some compiler pass or bundle extension, you'll see the following error message:

Argument "$rootNamespace" of service "maker.generator" is abstract (defined in MakerPass), did you forget to define it?

Sponsor the Symfony project.


About us

What a Symfony developer should know about the framework: News, Jobs, Tweets, Events, Videos,...

Resources

Find us on Twitter

Find us on Facebook