How to Inject Values Based on Complex Expressions
Warning: You are browsing the documentation for Symfony 4.x, which is no longer maintained.
Read the updated version of this page for Symfony 7.1 (the current stable version).
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 App\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: App\Mailer
. One way to do this is with an expression:
1 2 3 4 5 6 7 8 9 10 11
# config/services.yaml
services:
# ...
App\Mail\MailerConfiguration: ~
App\Mailer:
# the '@=' prefix is required when using expressions for arguments in YAML files
arguments: ['@=service("App\\Mail\\MailerConfiguration").getMailerMethod()']
# when using double-quoted strings, the backslash needs to be escaped twice (see https://yaml.org/spec/1.2/spec.html#id2787109)
# arguments: ["@=service('App\\\\Mail\\\\MailerConfiguration').getMailerMethod()"]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
<!-- 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="App\Mail\MailerConfiguration"></service>
<service id="App\Mailer">
<argument type="expression">service('App\\Mail\\MailerConfiguration').getMailerMethod()</argument>
</service>
</services>
</container>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// config/services.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use App\Mail\MailerConfiguration;
use App\Mailer;
return function(ContainerConfigurator $configurator) {
// ...
$services->set(MailerConfiguration::class);
$services->set(Mailer::class)
// because of the escaping applied by PHP, you must add 4 backslashes for each original backslash
->args([expr("service('App\\\\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 like
service
).
You also have access to the Container
via a container
variable. Here's another example:
1 2 3 4 5
# config/services.yaml
services:
App\Mailer:
# the '@=' prefix is required when using expressions for arguments in YAML files
arguments: ["@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'"]
1 2 3 4 5 6 7 8 9 10 11 12 13
<!-- 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="App\Mailer">
<argument type="expression">container.hasParameter('some_param') ? parameter('some_param') : 'default_value'</argument>
</service>
</services>
</container>
1 2 3 4 5 6 7 8 9 10 11
// config/services.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use App\Mailer;
return function(ContainerConfigurator $configurator) {
$services = $configurator->services();
$services->set(Mailer::class)
->args([expr("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).