Cover of the book Symfony 5: The Fast Track

Symfony 5: The Fast Track is the best book to learn modern Symfony development, from zero to production. +300 pages in full color showing how to combine Symfony with Docker, APIs, queues & async tasks, Webpack, Single-Page Applications, etc.

Buy printed version

How to Inject Values Based on Complex Expressions

How to Inject Values Based on Complex Expressions

The service container also supports an “expression” that allows you to inject very specific values into a service.

For example, suppose you have a service (not shown here), called AppBundle\Mail\MailerConfiguration, which has a getMailerMethod() method on it. This returns a string - like sendmail based on some configuration.

Suppose that you want to pass the result of this method as a constructor argument to another service: AppBundle\Mailer. One way to do this is with an expression:

  • YAML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # app/config/services.yml
    services:
        # ...
    
        AppBundle\Mail\MailerConfiguration: ~
    
        AppBundle\Mailer:
            # the '@=' prefix is required when using expressions for arguments in YAML files
            arguments: ["@=service('AppBundle\\\\Mail\\\\MailerConfiguration').getMailerMethod()"]
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- app/config/services.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <services>
            <!-- ... -->
    
            <service id="AppBundle\Mail\MailerConfiguration"></service>
    
            <service id="AppBundle\Mailer">
                <argument type="expression">service('App\\Mail\\MailerConfiguration').getMailerMethod()</argument>
            </service>
        </services>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // app/config/services.php
    use AppBundle\Mail\MailerConfiguration;
    use AppBundle\Mailer;
    use Symfony\Component\ExpressionLanguage\Expression;
    
    $container->autowire(MailerConfiguration::class);
    
    $container->autowire(Mailer::class)
        ->addArgument(new Expression('service("AppBundle\\\\Mail\\\\MailerConfiguration").getMailerMethod()'));
    

To learn more about the expression language syntax, see The Expression Syntax.

In this context, you have access to 2 functions:

service
Returns a given service (see the example above).
parameter
Returns a specific parameter value (syntax is just like service).

You also have access to the Symfony\Component\DependencyInjection\Container via a container variable. Here’s another example:

  • YAML
    1
    2
    3
    4
    services:
        AppBundle\Mailer:
            # the '@=' prefix is required when using expressions for arguments in YAML files
            arguments: ["@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'"]
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <services>
            <service id="AppBundle\Mailer">
                <argument type="expression">container.hasParameter('some_param') ? parameter('some_param') : 'default_value'</argument>
            </service>
        </services>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    use AppBundle\Mailer;
    use Symfony\Component\ExpressionLanguage\Expression;
    
    $container->autowire(Mailer::class)
        ->addArgument(new Expression(
            "container.hasParameter('some_param') ? parameter('some_param') : 'default_value'"
        ));
    

Expressions can be used in arguments, properties, as arguments with configurator and as arguments to calls (method calls).

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.