Laravel 5.7 版本, 如何更改路由为不区分大小写?

Laravel 5.7 版本, 如何更改路由为不区分大小写?

我自己尝试了搜索一些答案, 找到的都是老版本的做法, 例如,
php – 如何使Laravel中的路由不区分大小写?

而5.7 版本的 laravel, 已经更改了路由文件. 那么, 我该怎么做, 才能让路由不区分大小写呢?

例如: http://test.com/searchhttp://test.com/SEARCH, 是否有什么快捷的方式可以实现这样的功能?

请给我一个明确的方向, 谢谢.

当才华还支持不起理想时,就应该静下心来好好学习了。
qiuyuhome
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
TimJuly
最佳答案

@qiuyuhome 你这还是在 Laravel 框架里寻求解决方案啊,要跳出去。

你想一想路由的原理,是要先获取当前的REQUEST_URI然后在进行匹配吧,所以在程序进入到路由匹配之前你就把路径改了会有啥效果呢?

所以可以在index.php中直接修改

更进一步,你想要对请求进行一些处理,对于 Laravel 来说,放到Middleware中是不是更好一些。

4年前 评论
讨论数量: 10
TimJuly

Laravel 也是用 PHP 写的,所以最快捷的方式就是用 PHP 去解决,而不是一直跟 Laravel 较劲。

4年前 评论
qiuyuhome

@TimJuly 能否提供一个解决的思路方案, 我尝试使用正则, 但是也无效, 例如:

原本的路由:

Route::get('/games', 'GamesController@index')->name('games')

我想改为让url中的 /games, 不区分大小写, 我试着改动如下:

Route::get('/{games}', 'GamesController@index')->name('games')
    ->where(['games' => 'games/i']);

这样写是错误的. 会 404.

我想知道, 如何才能达到我的目的, 不区分大小写.

4年前 评论
TimJuly

@qiuyuhome 你这还是在 Laravel 框架里寻求解决方案啊,要跳出去。

你想一想路由的原理,是要先获取当前的REQUEST_URI然后在进行匹配吧,所以在程序进入到路由匹配之前你就把路径改了会有啥效果呢?

所以可以在index.php中直接修改

更进一步,你想要对请求进行一些处理,对于 Laravel 来说,放到Middleware中是不是更好一些。

4年前 评论
Summer

@TimJuly 的中间件方案是正解。

app/Http/Middleware/LowercaseRoutes.php

<?php

namespace App\Http\Middleware;

use Closure;
use \Illuminate\Support\Facades\Redirect;
class LowercaseRoutes
{
    /**
     * Run the request filter.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ( ! ctype_lower(preg_replace('/[^A-Za-z]/', '', $request->path())) && $request->path() !== "/") {
            $new_route = str_replace($request->path(), strtolower($request->path()), $request->fullUrl());
            return Redirect::to($new_route, 301);
        }
        return $next($request);
    }
}

app/Http/Kernel.php 文件里全局中间件组属性 $middleware 加上:

\App\Http\Middleware\LowercaseRoutes::class,

参考:https://gist.github.com/coreywelch/2de40f9...

使用时记得完整测试下。

4年前 评论
qiuyuhome

根据 @TimJuly 的提示. 我做了一下处理.

添加中间件. LowerCaseRoutes

<?php

namespace App\Http\Middleware;

use Closure;
use \Illuminate\Support\Facades\Redirect;

/**
 * 把大写uri转换为小写.
 * Class LowerCaseRoutes
 * @package App\Http\Middleware
 */
class LowerCaseRoutes
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (preg_match('/([A-Z]+)/', $request->path(), $match)) {
            $newRoute = str_replace($request->path(), strtolower($request->path()), $request->fullUrl());
            return Redirect::to($newRoute, 301);
        }

        return $next($request);
    }
}

已经实现路由不区分大小写, 如果有大写, 会301 跳转到小写的地址.

感谢 TimJuly

4年前 评论
qiuyuhome

@Summer 经测试, 使用ctype_lower 会有问题.

ctype_lower 的文档.

ctype_lower — 做小写字符检测

说明 ¶
ctype_lower ( string $text ) : bool
检查提供的 string 和 text 里面的字符是不是都是小写字母。

参数 ¶
text
需要被测试的字符串。

返回值 ¶
如果在当前的语言环境下 text 里面的每个字符都是小写字母,就返回 TRUE ;反之就返回 FALSE 。

所以, 如果首页, 会无限循环.

4年前 评论
TimJuly

@qiuyuhome
嗯,这种操作一定要多测试啊,我给你发个测试用例你测测

第一个:
GET /ABC?a=ABC&b=BCD

第二个:
POST /ABC

你看看程序都符合预期么

4年前 评论

为什么不区分大小写?严格点不是更好些吗?

4年前 评论
qiuyuhome

此方法, google 收录会遇到问题. 在找解决方案. 请不要用此方案.

google search console 会提示: redirect error. 原因在排查中.

4年前 评论
qiuyuhome

redirect error 已经处理, 可能的原因:

为了让url 不区分大小写, 做了判断, 如果uri 中存在大写字母, 则会301 到小写字母的url.

因为中文等文字, 会经过 urlencode 转换, urlencode的字符也会出现大写字母. 应该就是这个原因.

已经更改策略: 经过 urldecode 再判断是否包含大写字母.

<?php

namespace App\Http\Middleware;

use Closure;
use \Illuminate\Support\Facades\Redirect;

/**
 * 把大写uri转换为小写.
 * Class LowerCaseRoutes
 * @package App\Http\Middleware
 */
class LowerCaseRoutes
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (preg_match('/([A-Z]+)/', urldecode($request->path()), $match)) {
            $newRoute = str_replace(
                urldecode($request->path()),
                strtolower(urldecode($request->path())),
                urldecode($request->fullUrl())
            );

            return Redirect::to($newRoute, 301);
        }

        return $next($request);
    }
}
4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!