The story
Let's take this request https://nike.awesomedomainname.com/
as an example. I need a service that can fetch the nike
.
What I currently have
I've a service that fetches a router key from the @request_stack
. Let's use company as router key.
My main route as followed;
<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>
So I wrote this service to fetch the key and search for the company;
...
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
]);
}
}
}
....
}
And the service xml definition;
<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>
Now my problem is that in some cases the service app.current_company
doesn't return a Company
object instead a null
is given.
For example I have a custom UserProvider
that has the CompanyContextRequest
as a dependency to check if the user belongs to the company but I can't do so because it returns null
.
But it works perfectly in controllers and most other DI places.
Any suggestions? Is there something like priority for services like for event subscribers?
What I've tried
I've set the scope app.company_context_request
into request
and tried to fetch it from the container. With false results.
According to the Symfony docs this should work.
I run the latest stable version of Symfony v2.7.3
Edit: My goal is to have a service at all times that can tell me the current company that is based ofcourse on the subdomain.
Edit 2: This example is almost what I need except that in this example they use the users company and I need the company(key) from the subdomain.
The problem that your service app.company_context_request
is synthetic by nature - you cannot compile cause there is no request data at this moment.
How to Inject Instances into the Container
Why does it work in some places?
It works for cases when you call the services in the scope: after synthetic service Request
was inserted into Service Container and scope request
was activated. request
scope setup and RequestStack
filling happen into \Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel::handle
method and its parent one.
UserProvider
doesn't work cause its initialization happens out of request
scope: before Request
service is activated or after the app left the scope.
How to prevent it?
Save RequestStack
service to the service property and get current request not in the constructor but in the getCompany
method - at the moment of calling constructor Request
could be undefined;
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)
...
Add to service definition scope request
and get it with via container
inside another services: it will autogenerate exceptions when any services will try to get the one out of scope; There some constraints you should be aware: How to Work with Scopes This way is used in FOS
bundles, for instance, FOSOauthServer
.
If you will change code as in 1 then you can left service definition as it is
<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>
But current_company
should have scope
. request
to throw exception if Request
is not defined at the moment of initialization of the current_company
. Or you can use scope=prototype
(it will return new instance on every call) if you want to get current_company
in the moments when it is set and get null
in the moments when Request
doens't exist (out of scope, cli calls).
<service id="app.current_company" class="AppBundle\Entity\Company" scope="request">
<factory service="app.company_context_request" method="getCompany"/>
</service>
UPD It is not related to service priorities at all. It is related with container compilation mechanism. Compilation of the certain service happens on first call of this service: on explicit call or on compilation of dependent service.
With UserProvider
routes compilation of your service (so calling of the __construct) happens at the moment when Request
object is not yet in RequestStack
and in the Container
.
I don't really understand you question but if you want to set priority in YML is done like this
app.locale_listener:
class: Erik\AppBundle\Service\LocateListener
arguments: ["%kernel.default_locale%"]
tags:
- { name: kernel.event_subscriber, priority: 17 }
--- Edit ---
As first fix your ssl setup "This Connection is Untrusted" under linux firefox there are online tools to check if ssl is configured correctly.
As second the answer to your question you can set up some service or event listener that will read subdomain name, in case of service just use $this->get("serviceName")->getSubdomain()
how to get subdomain PHP function to get the subdomain of a URL
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With