如何使用scope
编辑本页警告:您正在浏览的文档欧宝体育电话欧宝娱乐app下载地址Symfony 2.7,现已不再维护。
读本页的更新版本用于Sy欧宝娱乐app下载地址mfony 6.2(当前稳定版本)。
如何使用scope
本文都是关于作用域的,这是与服务容器.如果您曾经在创建服务时遇到过提到“作用域”的错误,那么本文就是为您准备的。
请注意
如果你想注射请求
服务,简单的解决方案是注入request_stack
方法来访问当前请求getCurrentRequest ()方法(参见如何从服务容器中检索请求).本文的其余部分将以理论和更高级的方式讨论作用域。如果你要处理的是请求
服务,只需注入request_stack
.
理解范围
服务的作用域控制容器使用服务实例的时间。DependencyInjection组件提供了两个泛型作用域:
-
容器
(默认值): - 每次从容器中请求时,都会使用相同的实例。
-
原型
: - 每次请求服务时都会创建一个新实例。
的ContainerAwareHttpKernel还定义了第三个作用域:请求
.此作用域与请求绑定,这意味着为每个子请求创建一个新实例,并且在请求之外不可用(例如在CLI中)。
示例:客户端范围
除了请求
service(它有一个简单的解决方案,请参阅上面的说明),默认的Symfony容器中没有服务属于除欧宝娱乐app下载地址容器
而且原型
.但是为了本文的目的,假设存在另一个范围客户端
还有服务client_configuration
那是属于它的。这不是一个常见的情况,但想法是你可以进入和退出多个客户端
范围,每个范围都有自己的范围client_configuration
服务。
作用域为服务的依赖关系添加了约束:服务不能依赖于更窄作用域内的服务。例如,如果您创建一个泛型my_foo
服务,但尝试注入client_configuration
服务,你会收到一份ScopeWideningInjectionException编译容器时。阅读下面的边栏了解更多详细信息。
请注意
服务当然可以依赖于更广泛范围内的服务,而不会出现任何问题。
从更窄的范围使用服务
范围问题有两种解决方案:
- A)将您的服务置于与依赖项相同的范围(或更窄的范围)。如果你依赖于
client_configuration
服务,这意味着将新服务放在客户端
范围(见如何使用scope); - B)将整个容器传递给你的服务,并在每次需要时从容器中检索你的依赖项,以确保你有正确的实例——你的服务可以存在于默认的实例中
容器
范围(见如何使用scope).
每个场景将在以下部分中详细介绍。
请注意
在Symfony 欧宝娱乐app下载地址2.7之前,有另一种基于同步
服务。但是,从Symfony 2.7开始,这类服务就已经弃用了。欧宝娱乐app下载地址
A)改变服务范围
更改服务的范围应该在其定义中完成。这个例子假设梅勒
类有一个__construct ()
函数的第一个参数为ClientConfiguration
对象:
- YAML
- XML
- PHP
1 2 3 4 5 6
# app / config / services.yml服务:my_mailer:类:AppBundle \邮件\梅勒范围:客户端参数:(“@client_configuration”)
B)将容器作为服务的依赖项传递
将作用域设置为较窄的范围并不总是可能的(例如,分支扩展必须位于容器
因为Twig环境需要它作为依赖项)。在这些情况下,你可以将整个容器传递到你的服务中:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
/ / src / AppBundle /邮件/ Mailer.php名称空间AppBundle\邮件;使用欧宝娱乐app下载地址\组件\DependencyInjection\ContainerInterface;类梅勒{受保护的$容器;公共函数__construct(ContainerInterface$容器){$这->容器=$容器;}公共函数sendEmail(){$请求=$这->容器->get (“client_configuration”);/ /……使用这里的客户端配置做一些事情}}
谨慎
注意不要将客户端配置存储在对象的属性中,以便将来调用服务,因为这将导致与第一节中描述的相同的问题(除非Symfony无法检测到您的错误)。欧宝娱乐app下载地址
这个类的服务配置看起来像这样:
- YAML
- XML
- PHP
1 2 3 4 5 6
# app / config / services.yml服务:my_mailer:类:AppBundle \邮件\梅勒参数:(“@service_container”)# scope:容器可以省略,因为它是默认的
请注意
将整个容器注入到服务中通常不是一个好主意(只注入您需要的部分)。