Symfony路由包 - 从URL中删除区域设置的尾部斜杠:/ en /→/ en

时间:2016-10-18 12:40:47

标签: symfony url-routing

我有以下设置:

一切正常。但是,我无法解决这个问题:

  • 路由正确转换,路由以没有尾部斜杠结束:
    test.com/en/contact
  • 很遗憾, homepage 路由有一个尾部斜杠:
    test.com/en/ 应为 test.com/en
  • 也会将test.comtest.com/en的来电重定向至test.com/en/

如何摆脱这个尾随斜杠?

这是我的配置:

我在 parameters.yml 中设置了区域设置:

parameters:
    locale: de
    locales: [de, en]

我已在 config.yml 中配置了JMS路由包:

jms_i18n_routing:
    default_locale: "%locale%"
    locales: "%locales%"
    strategy: prefix

routing.yml 中的路线:

app:
    prefix: /
    resource: '@AppBundle/Controller/AppController.php'
    type: annotation
    options: { i18n: true }

我的索引/默认操作注释如下:

/**
 * @Route("/", name="homepage")
 */
public function indexAction(Request $request) {}

/web中的 .htaccess 文件是Symfony 3.1附带的样板文件

我已经尝试删除了传单中的/@Route("", name="homepage")),但没有任何运气。

2 个答案:

答案 0 :(得分:0)

我认为这是由于相对URL在使用时的工作原理:

<a href="{{ path('homepage') }}">Homepage<a>

生成的链接必须是&#34; /&#34;或者它不起作用,它将转到相同的实际页面而不是去主页。

答案 1 :(得分:0)

这是我的解决方案。首先,您必须将路径转换定义为空字符串。我正在使用yaml配置。

# AppBundle/Resources/config/routing.yml
homepage:
  path:     /
  defaults: { _controller: AppController:Page:index }

# AppBundle/Resources/translations/routes.de.yml
# AppBundle/Resources/translations/routes.en.yml
# and other routes translation files...
homepage: ''

现在删除了斜杠,但是当我们尝试访问没有区域设置参数的网页(www.mypage.com)时,它会首先重定向到www.mypage.com/en/,然后再重定向到www.mypage.com/en。

它是由JMS \ I18nRoutingBundle \ EventListener \ LocaleChoosingListener引起的,是onKernelException方法的最后一行:      $event->setResponse(new RedirectResponse($request- >getBaseUrl().'/'.$locale.'/'.($params ? '?'.http_build_query($params) : '')));这部分更精确:'$locale' . '/'

我们能做的就是重写这个听众。我这样做了:

# AppBundle/Resources/config/services.yml
parameters:
  jms_i18n_routing.locale_choosing_listener.class: AppBundle\EventListener\LocaleChoosingListener

# AppBundle/EventListener/LocaleChoosingListener
<?php

namespace AppBundle\EventListener;

use JMS\I18nRoutingBundle\EventListener\LocaleChoosingListener as BaseListener;
use JMS\I18nRoutingBundle\Router\LocaleResolverInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;

/**
 * Removing trailing slash from homepage requests
 * {@inheritdoc}
 */
class LocaleChoosingListener extends BaseListener
{
    private $defaultLocale;
    private $locales;
    private $localeResolver;

    public function __construct($defaultLocale, array $locales, LocaleResolverInterface $localeResolver)
    {
        parent::__construct($defaultLocale, $locales, $localeResolver);

        // If these properties were protected, we could remove the constructor.
        $this->defaultLocale = $defaultLocale;
        $this->locales = $locales;
        $this->localeResolver = $localeResolver;
    }

     public function onKernelException(GetResponseForExceptionEvent $event)
    {
        if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
            return;
        }

        $request = $event->getRequest();

        if ('' !== rtrim($request->getPathInfo(), '/')) {
            return;
        }

        $ex = $event->getException();

        if (!$ex instanceof NotFoundHttpException || !$ex->getPrevious() instanceof ResourceNotFoundException) {
            return;
        }

        $locale = $this->localeResolver->resolveLocale($request, $this->locales) ?: $this->defaultLocale;

        $request->setLocale($locale);

        $params = $request->query->all();
        unset($params['hl']);

        $event->setResponse(new RedirectResponse($request->getBaseUrl().'/'.$locale.($params ? '?'.http_build_query($params) : '')));
    }
}