ThinkPHP 8.0 注册中间件必须通过 app/middleware.php 唯一入口,返回含完整命名空间的数组,顺序决定执行时机,类需实现 MiddlewareInterface 并严格遵循命名与类型规范。

ThinkPHP 8.0 注册中间件必须走 app/middleware.php 这个唯一入口,且格式、位置、命名空间三者缺一不可——写错任意一项,中间件就静默不执行。
全局中间件:只认 app/middleware.php 返回的类名数组
该文件必须返回一个包含完整命名空间字符串的数组,不能用 use,不能写闭包,不能漏反斜杠:
- ✅ 正确写法(TP8 强制要求):
return [
\think\middleware\Lang::class,
\app\middleware\AuthCheck::class
]; - ❌ 错误写法举例:
—'think\middleware\Lang'(缺开头反斜杠,PHP 在当前命名空间下找类,报错)
—use think\middleware\Lang; return [Lang::class];(middleware.php是纯配置脚本,use被忽略)
—function() { ... }(TP8 禁止闭包,直接抛InvalidArgumentException)
注册顺序决定执行时机,关键逻辑靠位置保障
中间件在数组中的顺序 = 执行顺序。不同用途的中间件有明确先后要求:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- CORS 中间件 必须放在最前面,否则 Session 或鉴权中间件提前输出响应,导致 headers already sent;
-
Lang 中间件 需早于任何调用
lang()的逻辑(如验证提示、系统消息),推荐紧随 CORS 之后; -
AuthCheck 类权限中间件 必须放在 路由匹配完成之后,即不能在
SessionInit::class之前,更不能在已有鉴权中间件之后(避免重复拦截或拿不到路由名); - 若用
Route::group(...)->allowCrossDomain(),则无需额外注册 Cors 中间件,但该方式仅作用于该分组内路由。
中间件类本身要符合 TP8 接口规范
类必须实现 think\contract\MiddlewareInterface,且 handle() 方法需声明返回类型:
立即学习“PHP免费学习笔记(深入)”;
- ✅ 正确定义:
namespace app\middleware;
use think\contract\MiddlewareInterface;
class AuthCheck implements MiddlewareInterface {
public function handle($request, \Closure $next): \think\Response {
return $next($request);
}
} - ⚠️ 注意:
— 文件名必须与类名严格一致(AuthCheck.php→class AuthCheck);
— Linux 下大小写敏感,authcheck.php或AuthCheckMiddleware.php都会导致加载失败;
— PHP 8.1+ 环境下,若未标注返回类型,会触发TypeError且框架不兜底。
路由级与控制器级注册是补充,非替代
全局注册是基础,局部注册用于差异化控制:
-
路由级:在
route/app.php中绑定,只对指定路由生效:Route::get('admin/user', 'Admin/User@index')->middleware(\app\middleware\CheckPermission::class); -
控制器级:在控制器
initialize()中添加:$this->middleware->add(\app\middleware\LogRequest::class); - ⚠️ 注意:局部注册也必须传完整命名空间字符串或
::class常量,不能传字符串别名(如'auth'已废弃)。


















