理解PHP依赖注入容器(dependency injection container)系列(五) 使用XML 或 YAML 来描述服务
2016-09-25 11:04
971 查看
在上篇文章中,你已学会如何用sfServiceContainerBuilder类来描述服务了。今天在loaders和dumpers两个类的帮助下,我们将学会如何用XML或YAML 来描述服务。
Symfony容器提供了helper类,它可以通过“loader objects”的方式来加载服务。通常,每个组件都自带两个方法:
sfServiceContainerLoaderFileXml 加载 XML 文件
sfServiceContainerLoaderFileYaml 加载 YAML 文件
在深入XML和YAML标记前,我们先看看有关Symfony 注入组件的另一个组成部分:dumper类。dumper类接收一个容器对象,并将其转换成其它格式,这些格式包括XML,YAML。
用XML举例。我们先来使用sfServiceContainerDumperXml类,将上一篇例子中的容器中的服务定义转换成container.xml文件。
先回忆下我们是如何描述Zend_Mail服务的
将上面这个容器转换成XML,只需用下面的代码即可:
dumper类的构造函数的第一个参数接收的是一个服务容器builder类, dump()方法用来内省该容器,并将其转换成xml。如果一切正常, container.xml应该是这样
XML支持匿名服务。匿名服务是一种不需要名称的服务,它在被使用的上下文中直接定义。当你需要一个不会在另一个范围外使用的服务时(比如在一个类中调用另一个类时),它可以非常方便:
通过加载XML返回容器也很简单,用到了loader类
和dumper一样,loader类的构造函数第一个参数接收的是一个服务容器builder类,load()方法读取xml文件并向容器注册该xml描述的服务,然后像平常一样使用容器。
如果使用sfServiceContainerDumperYaml类生成文件,那么刚才的容器将会生成以下文件:
使用XML比YAML多一些好处:
当XML加载时,可以自动用services.xsd进行验证
一些IDE可生成XML
XML比YAML快
XML不需要外部依赖,而YAML需要用到sfYAML组件
当然也可以混合使用不同格式:
你可以通过GUI界面(有待完成)使用YAML或XML文件配置你的服务。但它也充满了更多有趣的可能性。
其中最重要的一个是导入其他“资源”的能力。一个资源可以是任何其他配置文件
import片列出了该类所需的资源。默认情况下,它查找与当前文件相对的路径文件,但也可以通过一个路径数组作为loader类构造函数的第二个参数来查找
你甚至可以在XML文件中导入YAML文件
同样可以在YAML中导入XML
导入功能提供了一种灵活的方式来组织你的服务定义文件,也是分享和重用服务定义文件的很好的方式。让我们来谈谈我们在第一篇文章中介绍的Web会话示例。
当在测试环境中使用session时,session存储对象可能不太受重视;相反,如果你有多个负载均衡的Web服务器,生产环境需要存储在MySQL数据库中。因此,我们需要一种方法,可以对于不同的环境,创建不同的配置文件,根据环境所需要进行导入
使用正确的配置就很简单了
我可以听到人们在抱怨使用XML来定义配置,因为XML可能不是地球上最可读的配置格式。在symfony框架中,你可以所有文件都用YAML格式写,也可以配置中分离服务的定义。你可以在services.xml文件定义服务,并存储在一个xml相关配置。也可以在YAML文件中定义参数(parameters.yml)。最后,通过内置ini loader,从一个标准的INI文件中读取参数
注意:INI文件不能定义服务,只能定义和解析参数
这些例子粗略描述了 loaders 和 dumpers的功能,我希望这篇文章对XML和YAML格式的强大功能作了较好的概述。对于那些怀疑容器加载多个文件进行配置后性能不理想的人 ,我认为你将在下一篇文章中改变想法。
Symfony容器提供了helper类,它可以通过“loader objects”的方式来加载服务。通常,每个组件都自带两个方法:
sfServiceContainerLoaderFileXml 加载 XML 文件
sfServiceContainerLoaderFileYaml 加载 YAML 文件
在深入XML和YAML标记前,我们先看看有关Symfony 注入组件的另一个组成部分:dumper类。dumper类接收一个容器对象,并将其转换成其它格式,这些格式包括XML,YAML。
用XML举例。我们先来使用sfServiceContainerDumperXml类,将上一篇例子中的容器中的服务定义转换成container.xml文件。
先回忆下我们是如何描述Zend_Mail服务的
require_once '/PATH/TO/sfServiceContainerAutoloader.php'; sfServiceContainerAutoloader::register(); $sc = new sfServiceContainerBuilder(); $sc-> register('mail.transport', 'Zend_Mail_Transport_Smtp')-> addArgument('smtp.gmail.com')-> addArgument(array( 'auth' => 'login', 'username' => '%mailer.username%', 'password' => '%mailer.password%', 'ssl' => 'ssl', 'port' => 465, ))-> setShared(false) ; $sc-> register('mailer', '%mailer.class%')-> addMethodCall('setDefaultTransport', array(new sfServiceReference('mail.transport'))) ;
将上面这个容器转换成XML,只需用下面的代码即可:
$dumper = new sfServiceContainerDumperXml($sc); file_put_contents('/somewhere/container.xml', $dumper->dump());
dumper类的构造函数的第一个参数接收的是一个服务容器builder类, dump()方法用来内省该容器,并将其转换成xml。如果一切正常, container.xml应该是这样
<?xml version="1.0" ?> <container xmlns="http://symfony-project.org/2.0/container"> <parameters> <parameter key="mailer.username">foo</parameter> <parameter key="mailer.password">bar</parameter> <parameter key="mailer.class">Zend_Mail</parameter> </parameters> <services> <service id="mail.transport" class="Zend_Mail_Transport_Smtp" shared="false"> <argument>smtp.gmail.com</argument> <argument type="collection"> <argument key="auth">login</argument> <argument key="username">%mailer.username%</argument> <argument key="password">%mailer.password%</argument> <argument key="ssl">ssl</argument> <argument key="port">465</argument> </argument> </service> <service id="mailer" class="%mailer.class%"> <call method="setDefaultTransport"> <argument type="service" id="mail.transport" /> </call> </service> </services> </container>
XML支持匿名服务。匿名服务是一种不需要名称的服务,它在被使用的上下文中直接定义。当你需要一个不会在另一个范围外使用的服务时(比如在一个类中调用另一个类时),它可以非常方便:
<service id="mailer" class="%mailer.class%"> <call method="setDefaultTransport"> <argument type="service"> <service class="Zend_Mail_Transport_Smtp"> <argument>smtp.gmail.com</argument> <argument type="collection"> <argument key="auth">login</argument> <argument key="username">%mailer.username%</argument> <argument key="password">%mailer.password%</argument> <argument key="ssl">ssl</argument> <argument key="port">465</argument> </argument> </service> </argument> </call> </service>
通过加载XML返回容器也很简单,用到了loader类
require_once '/PATH/TO/sfServiceContainerAutoloader.php'; sfServiceContainerAutoloader::register(); $sc = new sfServiceContainerBuilder(); $loader = new sfServiceContainerLoaderFileXml($sc); $loader->load('/somewhere/container.xml');
和dumper一样,loader类的构造函数第一个参数接收的是一个服务容器builder类,load()方法读取xml文件并向容器注册该xml描述的服务,然后像平常一样使用容器。
如果使用sfServiceContainerDumperYaml类生成文件,那么刚才的容器将会生成以下文件:
parameters: mailer.username: foo mailer.password: bar mailer.class: Zend_Mail services: mail.transport: class: Zend_Mail_Transport_Smtp arguments: [smtp.gmail.com, { auth: login, username: %mailer.username%, password: %mailer.password%, ssl: ssl, port: 465 }] shared: false mailer: class: %mailer.class% calls: - [setDefaultTransport, [@mail.transport]]
使用XML比YAML多一些好处:
当XML加载时,可以自动用services.xsd进行验证
一些IDE可生成XML
XML比YAML快
XML不需要外部依赖,而YAML需要用到sfYAML组件
当然也可以混合使用不同格式:
// Convert an XML container service definitions file to a YAML one $sc = new sfServiceContainerBuilder(); $loader = new sfServiceContainerLoaderFileXml($sc); $loader->load('/somewhere/container.xml'); $dumper = new sfServiceContainerDumperYaml($sc); file_put_contents('/somewhere/container.yml', $dumper->dump());
你可以通过GUI界面(有待完成)使用YAML或XML文件配置你的服务。但它也充满了更多有趣的可能性。
其中最重要的一个是导入其他“资源”的能力。一个资源可以是任何其他配置文件
<container xmlns="http://symfony-project.org/2.0/container"> <imports> <import resource="default.xml" /> </imports> <parameters> <!-- These parameters override the one defined in default.xml --> </parameters> <services> <!-- These service definitions override the one defined in default.xml --> </services> </container>
import片列出了该类所需的资源。默认情况下,它查找与当前文件相对的路径文件,但也可以通过一个路径数组作为loader类构造函数的第二个参数来查找
$loader = new sfServiceContainerLoaderFileXml($sc, array('/another/path')); $loader->load('/somewhere/container.xml');
你甚至可以在XML文件中导入YAML文件
$loader = new sfServiceContainerLoaderFileXml($sc, array('/another/path')); $loader->load('/somewhere/container.xml');
同样可以在YAML中导入XML
imports: - { resource: default.xml, class: sfServiceContainerLoaderFileXml }
导入功能提供了一种灵活的方式来组织你的服务定义文件,也是分享和重用服务定义文件的很好的方式。让我们来谈谈我们在第一篇文章中介绍的Web会话示例。
当在测试环境中使用session时,session存储对象可能不太受重视;相反,如果你有多个负载均衡的Web服务器,生产环境需要存储在MySQL数据库中。因此,我们需要一种方法,可以对于不同的环境,创建不同的配置文件,根据环境所需要进行导入
<!-- in /framework/config/default/session.xml --> <container xmlns="http://symfony-project.org/2.0/container"> <parameters> <parameter key="session.class">sfSessionStorage</parameter> </parameters> <!-- service definitions go here --> </container> <!-- in /project/config/session_test.xml --> <container xmlns="http://symfony-project.org/2.0/container"> <imports> <import resource="session.xml" /> </imports> <parameters> <parameter key="session.class">sfSessionTestStorage</parameter> </parameters> </container> <!-- in /project/config/session_prod.xml --> <container xmlns="http://symfony-project.org/2.0/container"> <imports> <import resource="session.xml" /> </imports> <parameters> <parameter key="session.class">sfMySQLSessionStorage</parameter> </parameters> </container>
使用正确的配置就很简单了
$loader = new sfServiceContainerLoaderFileXml($sc, array( '/framework/config/default/', '/project/config/', )); $loader->load('/project/config/session_'.$environment.'.xml');
我可以听到人们在抱怨使用XML来定义配置,因为XML可能不是地球上最可读的配置格式。在symfony框架中,你可以所有文件都用YAML格式写,也可以配置中分离服务的定义。你可以在services.xml文件定义服务,并存储在一个xml相关配置。也可以在YAML文件中定义参数(parameters.yml)。最后,通过内置ini loader,从一个标准的INI文件中读取参数
<!-- in /project/config/session_test.xml --> <container xmlns="http://symfony-project.org/2.0/container"> <imports> <import resource="config.ini" class="sfServiceContainerLoaderFileIni" /> </imports> </container> <!-- /project/config/config.ini --> [parameters] session.class = sfSessionTestStorage
注意:INI文件不能定义服务,只能定义和解析参数
这些例子粗略描述了 loaders 和 dumpers的功能,我希望这篇文章对XML和YAML格式的强大功能作了较好的概述。对于那些怀疑容器加载多个文件进行配置后性能不理想的人 ,我认为你将在下一篇文章中改变想法。
相关文章推荐
- 理解PHP依赖注入容器(dependency injection container)系列(四) Symfony服务容器:利用Builder创建服务
- 理解PHP依赖注入容器(dependency injection container)系列(三) Symfony服务容器介绍
- 理解PHP依赖注入容器(dependency injection container)系列(六)Symfony服务容器:速度至上
- 理解PHP依赖注入容器(dependency injection container)系列(二) 你需要依赖注入容器吗?
- 理解PHP依赖注入容器(dependency injection container)系列(一) 什么是依赖注入
- PHP程序员如何理解依赖注入容器(dependency injection container)
- php 依赖注入容器(dependency injection container)
- php 依赖注入容器(dependency injection container)
- [转] 深度理解依赖注入(Dependence Injection): Inversion of Control Containers and the Dependency Injection pattern
- 理解PHP 依赖注入|Laravel IoC容器
- 关于laravel 自动加载和依赖注入、服务容器、服务提供者的理解--1
- Spring框架xml配置文件 复杂类型属性注入——数组 list map properties DI dependency injection 依赖注入——属性值的注入依赖于建立的对象(堆空间)
- laravel服务容器-----深入理解控制反转(IoC)和依赖注入(DI)
- Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)
- Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)
- 理解PHP 依赖注入|Laravel IoC容器
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【四】——实现模型工厂,依赖注入以及格式配置
- laravel服务容器-----深入理解控制反转(IoC)和依赖注入(DI)
- Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)
- 【转】理解 PHP 依赖注入 | Laravel IoC容器