参数的引入

3.4 版本
维护中的版本

你在服务容器中可以定义“参数”,然后直接在服务定义的“任何部分”来直接使用它。这对于分离出某些你想要频繁变化的值是有用的。

取得和设置container参数 

操作容器参数,就是直接使用容器的“accessor方法(is/get/set/has)”来求得参数。你可以检查某个参数是否被定义在服务容器中:

1
$container->hasParameter('mailer.transport');

从容器中取出某个参数:

1
$container->getParameter('mailer.transport');

在容器中设置一个参数:

1
$container->setParameter('mailer.transport', 'sendmail');

上述参数名中的.符号只是symfony命名约定而已,目的是使参数更有可读性。参数是平面“键-值”元素,它们不能被组织成嵌套数组。

参数只能在容器被编译之前被设置好。更多编译容器的信息,请参阅本章的编译服务容器

配置文件中的参数 

你也可以使用配置文件中的parameters区块来设置参数:

1
2
parameters:
    mailer.transport: sendmail
1
2
3
4
5
6
7
8
9
<?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">
 
    <parameters>
        <parameter key="mailer.transport">sendmail</parameter>
    </parameters>
</container>
1
$container->setParameter('mailer.transport', 'sendmail');

如同直接从容器中取出参数值一样,你可以在配置文件中使用他它们。通过在参数两边添加百分比符号(%),你可以在任何地方指定参数,例如%mailer.transport%。这样做可以将参数值注入到服务中去,能够实现在【不同应用程序之间】或【单一应用程序中基于相同class的多个服务之间】去配置“不同版本的服务”。虽然你可以直接注入例程中的mail transport选项到Mailer类中,但是声明它是一个参数会使它容易被更改,而不是直接将transport依附并隐藏在服务定义之中:

1
2
3
4
5
6
7
parameters:
    mailer.transport: sendmail

services:
    mailer:
        class:     Mailer
        arguments: ['%mailer.transport%']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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">
 
    <parameters>
        <parameter key="mailer.transport">sendmail</parameter>
    </parameters>
 
    <services>
        <service id="mailer" class="Mailer">
            <argument>%mailer.transport%</argument>
        </service>
    </services>
</container>
1
2
3
4
5
6
7
use Symfony\Component\DependencyInjection\Reference;
 
$container->setParameter('mailer.transport', 'sendmail');
 
$container
    ->register('mailer', 'Mailer')
    ->addArgument('%mailer.transport%');

上述配置文件中的parameters标签之间的值,在xml配置文件中没有被裁切头尾空格。这意味着下述配置样例将包含\n sendmail \n:

1
2
3
<parameter key="mailer.transport">
    sendmail
</parameter>

在一些情况下(例如常量或类名字),这会抛出错误。为避免这种情况,你必须保证你的参数值像下面例子那样处于“行内”:

1
<parameter key=”mailer.transport”>sendmail</parameter>

当你这样把某个参数使用在很多地方时,需要的时候你只需在一处改变参数的值即可。

在参数中的百分号(译注:包括parameter参数和auguments参数),作为字符串的一部分,必须使用另一个百分号来加以“转义”:

1
arguments: ['http://symfony.com/?foo=%%s&bar=%%d']
1
<argument>http://symfony.com/?foo=%%s&amp;bar=%%d</argument>
1
->addArgument('http://symfony.com/?foo=%%s&bar=%%d');

数组参数 

参数并非只能是扁平字符串,也可以包含数组。对于XML格式的配置文件,你需要使用type="collection"这个属性,来标记所有的数组参数。

1
2
3
4
5
6
7
8
9
10
11
12
parameters:
    my_mailer.gateways:
        - mail1
        - mail2
        - mail3
    my_multilang.language_fallback:
        en:
            - en
            - fr
        fr:
            - fr
            - en
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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">
 
    <parameters>
        <parameter key="my_mailer.gateways" type="collection">
            <parameter>mail1</parameter>
            <parameter>mail2</parameter>
            <parameter>mail3</parameter>
        </parameter>
        <parameter key="my_multilang.language_fallback" type="collection">
            <parameter key="en" type="collection">
                <parameter>en</parameter>
                <parameter>fr</parameter>
            </parameter>
            <parameter key="fr" type="collection">
                <parameter>fr</parameter>
                <parameter>en</parameter>
            </parameter>
        </parameter>
    </parameters>
</container>
1
2
3
4
5
$container->setParameter('my_mailer.gateways', array('mail1', 'mail2', 'mail3'));
$container->setParameter('my_multilang.language_fallback', array(
    'en' => array('en', 'fr'),
    'fr' => array('fr', 'en'),
));

常量参数 

容器也支持设置PHP常量作为参数。为了利用这个功能,映射你的常量名字作为参数的值,然后添加type属性,取值为constant

1
2
3
4
5
6
7
8
9
10
<?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">
 
    <parameters>
        <parameter key="global.constant.value" type="constant">GLOBAL_CONSTANT</parameter>
        <parameter key="my_class.constant.value" type="constant">My_Class::CONSTANT_NAME</parameter>
    </parameters>
</container>
1
2
$container->setParameter('global.constant.value', GLOBAL_CONSTANT);
$container->setParameter('my_class.constant.value', My_Class::CONSTANT_NAME);

上述配置不能在YAML文件中工作。如果你使用YAML,你可以导入XML文件来利用常量参数这一功能:

1
2
imports:
    - { resource: parameters.xml }

Xml文件中的php关键字处理 

默认情况下,truefalsenull字符在xml格式配置文件中被自动转换成PHP关键字(分别是truefalsenull

1
2
3
4
5
6
7
<parameters>
    <parameter key="mailer.send_all_in_once">false</parameter>
</parameters>
 
<!-- after parsing 经过解析之后
$container->getParameter('mailer.send_all_in_once'); // returns false
-->

为避免这种行为,使用type属性,取值为“string”:

1
2
3
4
5
6
7
<parameters>
    <parameter key="mailer.some_parameter" type="string">true</parameter>
</parameters>
 
<!-- after parsing 经过解析之后
$container->getParameter('mailer.some_parameter'); // returns "true"
-->

以上不在YAML和PHP文件中发生,因为它们已经内建支持PHP关键字。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)