Как сделать маршруты в Laravel без учета регистра?

У меня есть проект в laravel, и в этом проекте есть много маршрутов.

Но я только что обнаружил, что маршруты чувствительны к регистру, значит /рекламодатель/отчеты отличается от /рекламодателя/отчетов.

Итак, я хочу, чтобы оба маршрута должны перенаправляться на один и тот же вид. В данный момент /рекламодатель/отчеты предоставляет исключение RouteNotFound.

Я читал о способе Route:: pattern(), но поскольку есть много маршрутов, мне придется приложить много усилий для этого. Итак, что я хочу, это лучший способ сделать это, если он есть.

Ответ 1

Чтобы сделать маршруты без учета регистра, вам необходимо изменить способ сопоставления маршрутов с URL-адресами. В Laravel все происходит в UriValidator, поэтому вам нужно создать свой собственный валидатор.

К счастью, как и большинство задач в Laravel, это не очень сложно.

Сначала создайте новый класс валидатора - единственное различие между этим и оригиналом заключается в том, что вы добавите модификатор i в конце регулярного выражения для скомпилированного маршрута для включения случая включения -чувствительное соответствие.

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

Во-вторых, вам нужно обновить список совпадений, которые используются для сопоставления URL-адреса маршруту и ​​заменить ваш оригинальный UriValidator.

Чтобы сделать это, добавьте следующее в начало файла routes.php:

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

Это удалит исходный валидатор и добавит ваш список в список валидаторов.

Имейте в виду, что этот код не был протестирован при запуске. Дайте мне знать, есть ли какие-либо опечатки или что-то не работает должным образом. Я буду более чем счастлив, чтобы это работало для вас:)

Ответ 2

Я написал суть, которая делает это: https://gist.github.com/samthomson/f670f9735d200773e543

Отредактируйте приложение /filters.php, чтобы проверить символы верхнего регистра на маршруте и перенаправить их на преобразованный маршрут.

Ответ 3

Я знаю, что это старый вопрос, но я столкнулся с той же проблемой, и я просто хочу поделиться своим решением.

В методе render(...) в Exceptions/Handler.php перехватите 404 исключения и подтвердите регистр URL, а затем перенаправьте так:

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

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

Вот оно.