如何从服务容器中取出Request

3.4 版本
维护中的版本

从Symfony2.4开始,作为注入request服务的替代,你应该注入request_stack服务。要使用Request对象,则通过getCurrentRequest()方法来得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace Acme\HelloBundle\Newsletter;
 
use Symfony\Component\HttpFoundation\RequestStack;
 
class NewsletterManager
{
    protected $requestStack;
 
    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }
 
    public function anyMethod()
    {
        $request = $this->requestStack->getCurrentRequest();
        // ... do something with the request
    }
 
    // ...
}

现在,在定义中注入 request_stack,就像注入其他服务一样:

1
2
3
4
5
# src/Acme/HelloBundle/Resources/config/services.yml
services:
    newsletter_manager:
        class:     Acme\HelloBundle\Newsletter\NewsletterManager
        arguments: ["@request_stack"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- src/Acme/HelloBundle/Resources/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="newsletter_manager"
            class="Acme\HelloBundle\Newsletter\NewsletterManager"
        >
            <argument type="service" id="request_stack"/>
        </service>
    </services>
</container>
1
2
3
4
5
6
7
8
9
// src/Acme/HelloBundle/Resources/config/services.php
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
 
// ...
$container->setDefinition('newsletter_manager', new Definition(
    'Acme\HelloBundle\Newsletter\NewsletterManager',
    array(new Reference('request_stack'))
));

为什么不再注入request服务? 

所有Symfony2内建的服务遵循同一原则:容器创建(该服务)的实例只有一个,当你需要得到它时,或当它被注入到其他服务时,容器就返回这个实例。在标准版Symfony中的唯一例外,就是request服务。

当你试图注入request对象到某个服务时,你可能会得到一个ScopeWideningInjectionException异常。这是因为request在生命周期中可以发生改变(例如,当一个sub-request子请求被创建时)

如果你将一个controller定义为服务,你可以得到一个Request对象而毋须将整个容器注入进来,这是通过把Request当成参数(argument)传给action方法来实现的。参考控制器中的Request对象参数以获得更多细节。

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

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