故事
我们以此请求https://nike.awesomedomainname.com/
为例。我需要一个可以获取nike
的服务。
我目前拥有什么
我从@request_stack
获取路由器密钥的服务。让我们使用公司作为路由器密钥。
我的主要路线如下;
<import host="{company}.domain.{_tld}" prefix="/" schemes="https" resource="@ExampleBundle/Resources/config/routing.xml">
<default key="_tld">%app_tld%</default>
<requirement key="_tld">com|dev</requirement>
<requirement key="company">[a-z0-9]+</requirement>
</import>
所以我写了这个服务来获取密钥并搜索公司;
...
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
class CompanyContextRequest {
protected $request;
protected $companyRepository;
public function __construct(RequestStack $requestStack, CompanyRepository $companyRepository) {
$this->request = $requestStack->getMasterRequest();
$this->companyRepository = $companyRepository;
}
public function getCompany()
{
if (null !== $this->request)
{
$company = $this->request->attributes->get('company');
if (null !== $company)
{
return $this->companyRepository->findOneBy([
'key' => $company
]);
}
}
}
....
}
服务xml定义;
<service id="app.company_context_request" class="AppBundle\Request\CompanyContextRequest">
<argument type="service" id="request_stack"/>
<argument type="service" id="orm_entity.company_repository"/>
</service>
<service id="app.current_company" class="AppBundle\Entity\Company">
<factory service="app.company_context_request" method="getCompany"/>
</service>
现在我的问题是,在某些情况下,服务app.current_company
不会返回Company
个对象,而是会发出null
。
例如,我有一个自定义UserProvider
,其CompanyContextRequest
作为依赖项来检查用户是否属于公司,但我不能这样做,因为它返回{{1} }。
但它在控制器和大多数其他DI位置都能很好地工作。
有什么建议吗?对事件订阅者这样的服务有优先权吗?
我尝试了什么
我已将范围null
设置为app.company_context_request
,并尝试从容器中获取它。结果不对。
根据Symfony文档,这应该有用。
我运行最新的稳定版Symfony v2.7.3
修改:我的目标是始终提供一项服务,告诉我当前的公司是基于子域的。
编辑2 :This example几乎是我需要的,除了在这个例子中他们使用用户公司,我需要来自子域的公司(密钥)。
答案 0 :(得分:3)
您的服务app.company_context_request
本质上是合成的问题 - 您无法编译,因为此时没有请求数据。
How to Inject Instances into the Container
为什么它在某些地方有用?
适用于在范围内调用服务的情况:合成服务Request
插入服务容器并且范围request
被激活后。 request
范围设置和RequestStack
填充发生在\Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel::handle
方法及其父方法中。
UserProvider
无法正常工作,因为其初始化发生在request
范围之外:激活Request
服务之前或应用程序离开范围之后。
如何预防?
将RequestStack
服务保存到服务属性并获取当前请求,而不是在构造函数中但在getCompany
方法中 - 在调用构造函数Request
时可能未定义;
public function __construct(RequestStack $requestStack, CompanyRepository $companyRepository)
{
// You cannot use request at this point cause at initialization of the service there could be no request yet
$this->requestStack = $requestStack;
$this->companyRepository = $companyRepository;
}
...
public function getCompany()
{
$request = $this->requestStack->getMasterRequest();
if (null !== $request)
...
添加到服务定义范围request
并在另一个服务中通过container
获取它:当任何服务试图使其超出范围时,它将自动生成异常;您应该注意一些限制:How to Work with Scopes这种方式在FOS
包中使用,例如FOSOauthServer
。
如果您将更改代码,则可以将服务定义保留为
<service id="app.company_context_request" class="AppBundle\Request\CompanyContextRequest">
<argument type="service" id="request_stack"/>
<argument type="service" id="orm_entity.company_repository"/>
</service>
但current_company
应该有scope
。 request
如果在Request
初始化时未定义current_company
,则抛出异常。或者你可以使用scope=prototype
(它会在每次调用时返回新实例)如果你希望在设置时获得current_company
并在{{1}时获得null
不存在(超出范围,cli调用)。
Request
<强> UPD 强> 它与服务优先级无关。它与容器编译机制有关。在第一次调用此服务时会对特定服务进行编译:显式调用或依赖服务的编译。
使用<service id="app.current_company" class="AppBundle\Entity\Company" scope="request">
<factory service="app.company_context_request" method="getCompany"/>
</service>
路由编译服务(因此调用 __ construct )发生在UserProvider
对象尚未进入Request
时RequestStack
。
答案 1 :(得分:2)
我真的不明白你的问题,但如果你想在YML中设置优先级就像这样
app.locale_listener:
class: Erik\AppBundle\Service\LocateListener
arguments: ["%kernel.default_locale%"]
tags:
- { name: kernel.event_subscriber, priority: 17 }
---编辑---
首先在linux firefox下修复你的ssl设置“This Connection is Untrusted”,有一些在线工具可以检查ssl是否配置正确。
作为您问题的第二个答案,您可以设置一些将读取子域名的服务或事件监听器,如果服务只使用$ this-&gt; get(“serviceName”) - &gt; getSubdomain()