Symfony2 中是否有任何配置允许使用不区分大小写的路由?
例如,以下路线应视为相同:
www.exmaple.com/all
www.exmaple.com/ALL
有一个关于此的拉取请求,但没有参考如何实现它。
从 Symfony2.4 开始,您现在可以为您的路由定义条件并使用表达式语言进行复杂检查。请参阅路由器:完全自定义的带有条件的路由匹配文档。
另一种解决方案是覆盖路由编译器类以更改/扩展路由匹配器的 php 编译:
contact:
path: /{media}
defaults: { _controller: AcmeDemoBundle:Main:contact, media: organic }
requirements:
media: email|organic|ad
options:
compiler_class: MyVendor\Component\Routing\CaseInsensitiveRouteCompiler
参见Symfony\Component\Routing\RouteCompiler类。
或者,正如 fabpot 在拉取请求评论中所说,您可以覆盖 Request::getPathInfo[1] 方法以始终返回小写字符串(使用 setFactory[2] 覆盖默认请求类)。
*1 github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L866
*2 github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L402
据我所知,这在 Symfony 2 中是不可能的。但是,您应该能够使用 Apache 的 mod_rewrite 来完成它。有关详细信息,请参阅此博客文章。
请务必阅读评论,因为初始帖子存在一些错误。
我发现了一种在纯 symfony(没有 apache mod_rewrite)中执行此操作的绝妙方法,而无需为每条路由创建不区分大小写的转发规则。
这利用了 twig ExceptionController。因为这发生在路由匹配失败(或由于其他原因引发 404 异常)之后,它不会破坏任何使用大写字母的现有路由 url(尽管这仍然是一个坏主意)。
namespace Application\Symfony\TwigBundle\Controller;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;
/**
* ExceptionController.
*/
class ExceptionController extends BaseExceptionController
{
/**
* Redirects 404s on urls with uppercase letters to the lowercase verion,
* then uses it's parent class to
* Convert an Exception to a Response.
*
* @param Request $request The request
* @param FlattenException $exception A FlattenException instance
* @param DebugLoggerInterface $logger A DebugLoggerInterface instance
*
* @return Response
*
* @throws \InvalidArgumentException When the exception template does not exist
*/
public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
{
if ( (string) $exception->getStatusCode() === '404' && preg_match('/[A-Z]/', $request->getPathInfo())) {
$lowercaseUrl = strtolower($request->getPathInfo());
if ($request->isMethod('POST')) {
return new RedirectResponse(
$lowercaseUrl,
'307'//307 status code preserves post information.
);
}
$queryString = $request->getQueryString();
return new RedirectResponse(
$lowercaseUrl.( strlen($queryString)>0 ? '?'.$queryString : '' ),
'301'//301 status code plays nice with search engines
);
}
return parent::showAction($request, $exception, $logger);
}
}
唯一的另一个技巧是您需要将此控制器配置为服务,您可以将正确的参数注入父类的构造函数:
在 services.yml
services:
application.custom.exception_controller:
class: Application\Symfony\TwigBundle\Controller\ExceptionController
arguments: [ "@twig", "%kernel.debug%" ]
在 config.yml 中:
twig:
exception_controller: application.custom.exception_controller:showAction
当然,您可以将这个控制器和服务定义粘贴到任何地方