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...