Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make routes in Laravel case insensitive?

I have a project in laravel and there are many routes in that project.

But i just discovered that the routes are all case sensitive, means /advertiser/reports is different than /advertiser/Reports .

So what i want is both the routes should redirect to same view. Currently /advertiser/Reports gives RouteNotFound Exception.

I have read about the Route::pattern() way of doing it but since there are many routes i'll have to put in a lot of efforts for that. So, what i want is a better way of doing it, if there is any.

like image 589
Nishant Srivastava Avatar asked Aug 12 '15 12:08

Nishant Srivastava


People also ask

Are routes case sensitive?

on Jul 27, 2020. The standard is that the path in a URL is case-sensitive. If you want to make case-insensitive paths work, I might look into using custom routes and redirect everything to a lower-case path.

Is Laravel case sensitive?

Laravel Routing Case-insensitive routes will match a GET request to /login but will not match a GET request to /Login . In order to make your routes case-insensitive, you need to create a new validator class that will match requested URLs against defined routes.

What is route :: has in Laravel?

Routing in Laravel allows you to route all your application requests to its appropriate controller. The main and primary routes in Laravel acknowledge and accept a URI (Uniform Resource Identifier) along with a closure, given that it should have to be a simple and expressive way of routing.


Video Answer


2 Answers

In order to make routes case-insensitive you'll need to modify the way routes are matched with the URLs. In Laravel, it all happens in UriValidator object so you'll need to create your own validator.

Luckily, like most tasks in Laravel, it's not really complicated.

First, create the new validator class - the only difference between this one and the original is that you'll append the i modifier at the end of regular expression for the compiled route to switch enable case-insensitive matching.

<?php namespace Your\Namespace;

use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use Illuminate\Routing\Matching\ValidatorInterface;

class CaseInsensitiveUriValidator implements ValidatorInterface
{
  public function matches(Route $route, Request $request)
  {
    $path = $request->path() == '/' ? '/' : '/'.$request->path();
    return preg_match(preg_replace('/$/','i', $route->getCompiled()->getRegex()), rawurldecode($path));
  }
}

Secondly, you need to update the list of matchers that are used to match URL to a route and replace the original UriValidator with yours.

In order to do that, add the following at the top of your routes.php file:

<?php
use Illuminate\Routing\Route as IlluminateRoute;
use Your\Namespace\CaseInsensitiveUriValidator;
use Illuminate\Routing\Matching\UriValidator;

$validators = IlluminateRoute::getValidators();
$validators[] = new CaseInsensitiveUriValidator;
IlluminateRoute::$validators = array_filter($validators, function($validator) { 
  return get_class($validator) != UriValidator::class;
});

This will remove the original validator and add yours to the list of validators.

Keep in mind that this code has not been tested by running. Let me know if there are any typos or something doesn't work as expected. I'll be more than happy to get that working for you :)

like image 87
jedrzej.kurylo Avatar answered Oct 04 '22 18:10

jedrzej.kurylo


I know this is an old question but I came across this same problem and I just want to share my solution.

On method render(...) at Exceptions/Handler.php, catch 404 exceptions and validate the case of the URL then redirect like this:

public function render($request, Exception $exception)
{
    $url = $request->url();
    $loweredCaseUrl = strtolower($url);
    if (
        $exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException &&
        $url !== $loweredCaseUrl
    ) {
        return redirect($loweredCaseUrl);
    }

    return parent::render($request, $exception);
}

That's it.

like image 40
rmondesilva Avatar answered Oct 04 '22 19:10

rmondesilva