如何注入基于复杂表达式的值
服务容器支持一种称为“表达式”的语言,允许你将非常特殊的值注入到服务中。
例如,假设你有一个新的服务(不在这里明示),叫mailer_configuration
,它有一个getMailerMethod()
方法,基于某些配置来返回像一个像sendmail
这样的字符串。你还记得,app.mailer
服务的第一个参数就是sendmail
:
1 2 3 4 5 |
# app/config/services.yml
services:
app.mailer:
class: AppBundle\Mailer
arguments: [sendmail] |
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> |
1 2 3 4 5 6 7 |
// app/config/services.php
use Symfony\Component\DependencyInjection\Definition;
$container->setDefinition('app.mailer', new Definition(
'AppBundle\Mailer',
array('sendmail')
)); |
但是有别于在配置服务时写死,我们如何才能从新服务mailer_configuration
的getMailerMethod()
方法中得到这个值呢? 其中一个办法就是使用表达式:
1 2 3 4 5 |
# app/config/config.yml
services:
my_mailer:
class: Acme\HelloBundle\Mailer
arguments: ["@=service('mailer_configuration').getMailerMethod()"] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!-- 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="Acme\HelloBundle\Mailer">
<argument type="expression">service('mailer_configuration').getMailerMethod()</argument>
</service>
</services>
</container> |
1 2 3 4 5 6 7 8 |
// app/config/config.php
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\ExpressionLanguage\Expression;
$container->setDefinition('my_mailer', new Definition(
'Acme\HelloBundle\Mailer',
array(new Expression('service("mailer_configuration").getMailerMethod()'))
)); |
关于更多表达式语法,参考这里The Expression Syntax。
此处的上下文,你使用了两个功能:
service
返回一个指定服务(见上面代码)
parameter
返回一个参数值(用法和service类似)
你还可以使用ContainerBuilder
,通过container 变量来实现。下面是另一个例子:
1 2 3 4 |
services:
my_mailer:
class: Acme\HelloBundle\Mailer
arguments: ["@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'"] |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?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="Acme\HelloBundle\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 |
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\ExpressionLanguage\Expression;
$container->setDefinition('my_mailer', new Definition(
'Acme\HelloBundle\Mailer',
array(new Expression(
"container.hasParameter('some_param') ? parameter('some_param') : 'default_value'"
))
)); |
表达式可以使用在服务定义中的方法参数(arguments
to method call)和属性(properties
)中。注:作为参数时,也可以是configurator的参数。(译注:此处高难,参考DI组件文档相关)