关于TP8的路由中间件别名的配置问题

2025年5月31日 999+浏览

TP8相对于TP6有挺多改动,这不,我把一个项目部署到TP8的时候就遇到了路由中间件别名的配置问题,在查阅官方文档(有必要吐槽一下官方文档太混乱了,都TP8了,文档还是和TP5差不多一样邋遢)和AI解决方案都是无效的。好在经过自行反复测试及验证才解决问题。

故障复现:

[图片之后再补] 报的错误分别有:

①:【#0 [2]ErrorException in Middleware.php line 194 Undefined array key 0】

②:【#0 [0]ClassNotFoundException in Container.php line 382 类不存在: check】

有关代码文件及基本环境:

1、在app\middleware\Check.php

    public function handle($request, \Closure $next)
    {
        if (!session('?user_id')) {
            return redirect('/');
        }
        return $next($request);
    }

2、在app\middleware.php


use think\middleware\SessionInit;
use think\middleware\CheckRequestCache;
// 全局中间件定义文件
return [
    // 全局请求缓存
    CheckRequestCache::class,
    // Session初始化 
    SessionInit::class,

    // 全局
    // 'check',
    
];

3、在config\middlewarep.php

return [
    // 路由中间件别名
    // route_middleware
    'alias' => [
        'check' => \app\middleware\Check::class,
    ],

];

4、在route\app.php

Route::get('/', 'indexController/index')->middleware('check');

5、app\controller\indexController.php

    // @测试
    public function hello($name = 'ThinkPHP8')
    {   
        return 'hello,' . $name;
    }

上述代码是已经过验证并且可以成功运行且功能无误的。

除此之外,有关其它一些解决过程中遇到的问题也值得分享出来:

1、要保证 config/middleware.php 中的配置正确,并且使用了完整的命名空间:

return [
    // 路由中间件
    //类名前的反斜杠\不能省略,否则 PHP 会在当前命名空间下查找类。
    //据说route_middleware和alias的效果是一样的。暂时不明白原因。
    'route_middleware' => [
        'check' => \app\middleware\Check::class, // 确认有反斜杠 \
    ],
];

2、清除缓存文件

缓存可能会使配置无法及时更新,执行下面的命令清除缓存:

php think clear       # 清除缓存 ##不用加其它参数。

3、直接使用类名,跳过别名解析 或者 直接使用路径+类名

use app\middleware\Check;

Route::get('/index', 'indexController/index') ->middleware(Check::class); 

4、调试中间件加载过程

在 vendor/thinkphp/framework/src/think/Middleware.php 文件中添加调试代码:

// 在 Middleware.php 中找到解析别名的位置
public function alias(string $name)
{
    // 添加日志
    \think\facade\Log::debug('尝试解析中间件别名: ' . $name);
    \think\facade\Log::debug('可用别名配置: ' . json_encode($this->routeMiddleware));
    
    if (isset($this->routeMiddleware[$name])) {
        return $this->routeMiddleware[$name];
    }
    
    throw new ClassNotFoundException('类不存在: ' . $name, $name);
}
//然后 查看日志文件,确认:框架是否尝试解析你定义 以及 别名配置是否被正确加载。

5、如果你需要在路由中传递参数。

Route::get('/index', 'indexController@index')->middleware(['check', 'admin']);
//其中 'auth' 是中间件别名,'admin' 就是传给中间件的参数。

你的中间件相关代码如下(参数相关部分):

if ($role && $user->role !== $role) {
            return json(['status' => 'error', 'message' => "Permission denied for role:{$role}"], 403);
}

但是,目前我又发现一个新问题,目前还不清楚原因,等我解决之后再发出来吧 ...o(╥﹏╥)o...