【问题标题】:Symfony2; domain/host based info in controller and base templateSymfony2;控制器和基本模板中基于域/主机的信息
【发布时间】:2015-05-21 13:38:41
【问题描述】:

我正在构建一个 symfony2 应用程序,该应用程序可根据用于访问该站点的域进行配置。 为了简化这个问题,假设数据库中有一个“域”实体,其中包含主机名和进一步的配置。 考虑细微的模板差异,页眉/页脚的一些差异。提供的产品有所不同。 可用的路线不会有所不同。

有两个地方我需要这个域对象。 * 在 Controller::action 中 * 在基本模板中(即使控制器不需要它) 我在其他地方不需要它,如果需要,我可以简单地从控制器传递它。

在不产生太多开销并且在我们实际上不需要它时不获取该对象的最佳方法是什么。

到目前为止我的一些想法: * 我可以覆盖 ControllerResolver 并根据 Request 对象确定 Domain 对象。虽然我似乎无法访问那里的 ServiceContainer。 * 我可以向 BaseController 添加一些方法,当我在 Controller:Action 中时,它可以为我检索域。 * 对于模板中的使用,我可以创建一个添加全局变量的 TwigExtension。但它需要访问 Request 对象或 RequestStack。另外,这只会在模板中帮助我,我可能会做两次同样的事情。

您有什么建议吗?

【问题讨论】:

    标签: symfony


    【解决方案1】:

    不知道这是否是最好的解决方案,但到目前为止对我来说效果很好。

    由于域信息取决于请求,因此它不是服务,因此不要尝试将其注入服务中,否则您会头疼的。设置域信息最自然的地方是在请求中,并允许控制器读取此信息以与服务交互。

    因此,您可以设置一个内核事件侦听器,该侦听器从数据库中读取信息并设置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

    【讨论】:

    • 感谢回复;将彻底查看,好像它是我们要使用的解决方案。看起来很有希望。将请求传递给服务不是我的意图,我宁愿要求在从控制器“调用服务上的方法”时传递这些值。
    • 抱歉回复慢。我忘记了这个问题。但答案是正确的。
    猜你喜欢
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-18
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 2015-01-16
    相关资源
    最近更新 更多