How can I make routing case insensitive in Symfony2?

雨燕双飞 提交于 2019-12-23 16:34:44

问题


Is there any configuration in Symfony2 that allow use of case Insensitive routing?

For example, routes below should be treated as they are the same:

www.exmaple.com/all 
www.exmaple.com/ALL

There is a pull request about this, but no reference how to make it happen.


回答1:


I found a nifty way to do this in pure symfony (no apache mod_rewrite) without having to create a case-insensitive forwarding rule for every route.

This utilizes the twig ExceptionController. Because this occures after the routing has failed to match (or a 404 exception has been thrown for some other reason) it won't break any existing routing urls that use capitals (though that would still be a bad idea).

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);
    }
}

The only other trick is that you need to configure this controller as a service you can inject the correct arguments into the parent class's constructor:

in services.yml

services:
    application.custom.exception_controller:
        class: Application\Symfony\TwigBundle\Controller\ExceptionController
        arguments: [ "@twig", "%kernel.debug%" ]

in config.yml:

twig:
    exception_controller: application.custom.exception_controller:showAction

Of course, you can stick this controller and service definition anywhere




回答2:


As far as I know, this isn't possible with Symfony 2. However, you should be able to accomplish it with Apache's mod_rewrite. See this blog post for details.

Make sure to read the comments, as there are some errors with the initial post.




回答3:


As of Symfony2.4, you can now define condition to your route and use the expression language to do complexe check. See Router: Completely Customized Route Matching with Conditions documentation.

Another solution would be to override the route compiler class to change/extend the php compilation of your route matcher:

contact:
    path:     /{media}
    defaults: { _controller: AcmeDemoBundle:Main:contact, media: organic }
    requirements:
        media: email|organic|ad
    options:
        compiler_class: MyVendor\Component\Routing\CaseInsensitiveRouteCompiler

See Symfony\Component\Routing\RouteCompiler class.

Or, as fabpot said in the pull request comment, your could override Request::getPathInfo[1] method to always return a lowercase string (use the setFactory[2] to override default request class).

*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



来源:https://stackoverflow.com/questions/17538890/how-can-i-make-routing-case-insensitive-in-symfony2

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!