不知道这是否是最好的解决方案,但到目前为止对我来说效果很好。
由于域信息取决于请求,因此它不是服务,因此不要尝试将其注入服务中,否则您会头疼的。设置域信息最自然的地方是在请求中,并允许控制器读取此信息以与服务交互。
因此,您可以设置一个内核事件侦听器,该侦听器从数据库中读取信息并设置domain Request 属性,如下所示:
<?php
namespace Acme\SiteBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Doctrine\ORM\EntityRepository;
class DomainSubscriber implements EventSubscriberInterface
{
protected $domainRepository;
public static function getSubscribedEvents()
{
return array(
KernelEvents::REQUEST => 'onKernelRequest'
);
}
public function __construct(EntityRepository $domainRepository)
{
$this->domainRepository = $domainRepository;
}
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
// Console/CLI commands don't have Domain info
if ($request === null)
return;
$domain = $this->domainRepository->find($request->getHost());
if ($domain === null)
throw new \RuntimeException(sprintf("Cannot find domain %s", $request->getHost()));
$request->attributes->set('domain', $domain);
}
}
必须在services.yml(或XML)中注册:
acme_site.manager:
class: Doctrine\ORM\EntityManager
factory_service: doctrine
factory_method: getManager
acme_site.domain_repository:
class: Doctrine\ORM\EntityRepository
factory_service: acme_site.manager
factory_method: getRepository
arguments:
- 'AcmeSiteBundle:Domain'
acme_site.domain_subscriber:
class: Acme\SiteBundle\EventListener\DomainSubscriber
arguments:
- "@acme_site.domain_repository"
tags:
- { name: kernel.event_subscriber }
在您的控制器中,您现在只需执行以下操作即可访问数据:
public function someAction(Request $request) {
$domain = $request->attributes->get('domain');
$domain->getWhatever();
}
在 Twig 中,您始终可以通过以下方式访问请求:
{% set domain = app.request.attributes.get('domain') %}
whatever: {{ domain.whatever }}
希望对您有所帮助!
免责声明:代码是复制粘贴然后编辑的,因此可能包含一些小错误。
注意:如果你真的需要在服务中注入请求,那么我建议你阅读有关RequestStack(Symfony 2.4+)的文档,或者使用setRequest 方法并注意container scopes。