Ton*_*nov 53 service dependency-injection symfony
当我尝试将@request注入我的任何服务时,我得到以下异常:
ScopeWideningInjectionException:检测范围扩展注入:定义"service.navigation"引用属于较窄范围的服务"请求".通常,将"service.navigation"移动到范围"请求"更安全,或者通过注入容器本身来依赖提供者模式,并在每次需要时请求服务"请求".在极少数情况下,特殊情况可能没有必要,那么您可以将引用设置为strict = false以消除此错误.
什么是最好的方法?我应该尝试设置这个strict=false
以及如何,或者我应该不注入请求服务,而是每次调用我需要的函数时通过我的控制器将其传递给服务?
其他可能性是注入内核并从那里获取它,但在我的服务中我只使用@router和@request,因此注入整个内核将是不合理的.
谢谢!
Dan*_*ows 98
在Symfony 2.4中,这已经发生了变化.现在,您可以注入'request_stack'服务.
例如:
use Symfony\Component\HttpFoundation\RequestStack;
class MyService
{
protected $request;
public function setRequest(RequestStack $request_stack)
{
$this->request = $request_stack->getCurrentRequest();
}
}
Run Code Online (Sandbox Code Playgroud)
在你的config.yml中:
services:
my.service:
class: Acme\DemoBundle\MyService
calls:
- [setRequest, ["@request_stack"]]
Run Code Online (Sandbox Code Playgroud)
完整文档在这里:http://symfony.com/blog/new-in-symfony-2-4-the-request-stack
Cer*_*rad 31
我认为官方文件说的可能存在一些误解.在大多数情况下,您确实希望直接使用scope="request"
service元素上的属性注入请求.这使得Scope Widening消失了.
<service
id="zayso_core.openid.rpx"
class="Zayso\CoreBundle\Component\OpenidRpx" public="true" scope="request">
Run Code Online (Sandbox Code Playgroud)
或者在yml中
zayso_core.openid.rpx:
class: Zayso\CoreBundle\Component\OpenidRpx
public: true
scope: request
Run Code Online (Sandbox Code Playgroud)
它仅适用于需要注入容器的特定特殊情况,例如Twig扩展.
并且在范围页面中甚至没有提到内核.注入内核比注入容器要差得多(概念上).
更新:对于S2.4及更新版本,请使用@ Blowski的答案.
小智 6
我发现创建服务的最佳方式是使用请求服务,而不是依赖于整个容器,并且仍然不需要具有请求范围,就是创建一个接收容器的RequestInjector服务.然后将其注入要使用请求对象的服务中
class RequestInjector{
protected $container;
public function __construct(Container $container){
$this->container = $container;
}
public function getRequest(){
return $this->container->get('request');
}
}
class SomeService{
protected $requestInjector;
public function __construct(RequestInjector $requestInjector){
$this->requestInjector = $requestInjector;
}
}
Run Code Online (Sandbox Code Playgroud)
对于services.yml
request_injector:
class: RequestInjector
public: false
arguments: ['@service_container']
some_service:
class: SomeService
arguments: ['@request_injector']
Run Code Online (Sandbox Code Playgroud)
注意:这个答案是在2012年写的,那时Symfony 2.0已经推出,然后这是一个很好的方法!请不要再downvote :)
今天我自己也遇到了同样的问题,所以这是我的5美分.根据官方文档,通常不需要注入request
您的服务.在您的服务类中,您可以传递kernel
容器(注入它不是一个很大的开销,因为它听起来),然后request
像这样访问:
public function __construct(\AppKernel $kernel)
{
$this->kernel = $kernel;
}
public function getRequest()
{
if ($this->kernel->getContainer()->has('request')) {
$request = $this->kernel->getContainer()->get('request');
} else {
$request = Request::createFromGlobals();
}
return $request;
}
Run Code Online (Sandbox Code Playgroud)
当在CLI中访问服务时(例如,在单元测试期间),此代码也正常工作.