【问题标题】:How can I support multiple dynamic hosts within Symfony Routing?如何在 Symfony 路由中支持多个动态主机?
【发布时间】:2021-11-19 14:57:50
【问题描述】:

在我的 Symfony 应用程序 (Symfony 5.3) 中,我必须支持以下场景,其中包含属于多个应用程序上下文的多个主机/域(即自己的防火墙和自己的控制器,有时也是共享控制器):

main-domain.tld -> main_context
main-domain2.tld -> main_context
service.main-domain.tld -> service_context
service.main-domain2.tld -> service_context
service.maybe-several-other-brand-domains.tld -> service_context
admin.main-domain.tld -> admin_context
admin.main-domain2.tld -> admin_context
admin.maybe-several-other-brand-domains.tld -> admin_context

它是如何开始的

在我们拥有多个品牌/域之前,我们有两个主要的应用上下文,它们由它们自己的主机名解决。所以我们做了这样的事情来将控制器分配给上下文:

#[Route(
    path: '/',
    requirements: ['domain' => '%app.public_hostname_context1%'],
    defaults: ['domain' => '%app.public_hostname_context1%'],
    host: '{domain}',
)]
# where app.public_hostname_context1 is a hostname configured in the .env.local

进展如何

这很有效,直到我们决定为其中一种情境设置多个有效主机,事实上这与品牌推广的需要一样多。所以我做了一些研究并遇到了问题,我无法访问defaults 配置中的当前主机名,因此必须在我生成的每个 url 上明确设置域。

问题是

你将如何解决这个要求?

【问题讨论】:

    标签: php symfony


    【解决方案1】:

    我将我的第一个解决方案方法作为直接答案发布,所以请讨论它或与更好的方法一起闪耀。也许,我已经监督了一些事情,我有一种轻微的感觉,那个解决方案可能不是最好的。对于其他偶然发现相同要求的人,整个问题将记录至少一种解决方法。 :)

    首先,从路由定义中删除defaults,并为上下文的多个有效域提供模式:

    #[Route(
        path: '/',
        requirements: ['domain' => '%app.public_hostnames_context1_pattern%'],
        host: '{domain}',
    )]
    # app.public_hostname_context1_pattern is a pattern configured in the .env.local
    # containing all possible hostnames for that context like
    # PUBLIC_HOSTNAME_CONTEXT1_PATTERN=(?:service\.main-domain\.tld|service\.main-domain2\.tld)
    

    要将当前主机名设置为所有路由的域参数的默认值,我有一个 2012 年的 RequestListener inspired by this answer 在 RouterListener 工作之前设置它。

    在我的 services.yaml 中:

        # must be called before the RouterListener (with priority 32) to load the domain
        App\EventListener\RequestListener:
            tags:
                - { name: kernel.event_listener, event: kernel.request, priority: 33 }
    

    还有 RequestListener:

    <?php
    declare(strict_types=1);
    namespace App\EventListener;
    
    use Symfony\Component\HttpKernel\Event\RequestEvent;
    use Symfony\Component\Routing\RouterInterface;
    
    class RequestListener
    {
        public function __construct(
            private RouterInterface $router,
        ){}
    
        public function onKernelRequest(RequestEvent $event)
        {
            if (false === $this->router->getContext()->hasParameter('domain')) {
                $this->router->getContext()->setParameter('domain', $event->getRequest()->getHost());
            }
        }
    }
    

    这样做的好处是,当我创建 URL 时,我仍然可以覆盖 domain 参数。但我看到的一个缺点是:当我为另一个上下文生成 URL 并且没有明确设置域时,会引发错误,因为现在当前请求的主机被用作另一个上下文的域,即不允许在要求范围内的模式。我可以忍受这一点。你呢?

    【讨论】:

      猜你喜欢
      • 2016-02-07
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 2020-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多