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 third service (not shown here), called mailer_configuration, which has a getMailerMethod() method on it, which will return a string like sendmail based on some configuration. Remember that the first argument to the my_mailer service is the simple string sendmail:

  • YAML
    1
    2
    3
    4
    5
    # app/config/services.yml
    services:
        app.mailer:
            class:        AppBundle\Mailer
            arguments:    [sendmail]
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    <!-- 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
            http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <services>
            <service id="app.mailer" class="AppBundle\Mailer">
                <argument>sendmail</argument>
            </service>
        </services>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // app/config/services.php
    use AppBundle\Mailer;
    
    $container->register('app.mailer', Mailer::class)
        ->addArgument('sendmail');
    

But instead of hardcoding this, how could we get this value from the getMailerMethod() of the new mailer_configuration service? One way is to use an expression:

  • YAML
    1
    2
    3
    4
    5
    # app/config/config.yml
    services:
        my_mailer:
            class:     AppBundle\Mailer
            arguments: ["@=service('mailer_configuration').getMailerMethod()"]
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    <!-- app/config/config.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
            http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <services>
            <service id="my_mailer" class="AppBundle\Mailer">
                <argument type="expression">service('mailer_configuration').getMailerMethod()</argument>
            </service>
        </services>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    // app/config/config.php
    use AppBundle\Mailer;
    use Symfony\Component\ExpressionLanguage\Expression;
    
    $container->register('my_mailer', Mailer::class)
        ->addArgument(new Expression('service("mailer_configuration").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 ContainerBuilder via a container variable. Here's another example:

  • YAML
    1
    2
    3
    4
    services:
        my_mailer:
            class:     AppBundle\Mailer
            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
            http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <services>
            <service id="my_mailer" class="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->register('my_mailer', 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.