TP8中间件必须实现think\contract\MiddlewareInterface接口并标注handle()返回类型为\think\Response,注册时须用::class常量而非字符串,否则静默失效。

TP8 中间件必须实现 MiddlewareInterface 接口
TP8 不再接受裸 handle() 方法的中间件类,哪怕它在 TP6 下能跑通。框架启动时通过反射检查类型契约,没 implements think\contract\MiddlewareInterface 就直接跳过,不报错也不执行——请求看似“正常”,实则中间件逻辑完全失效。
常见错误现象:登录校验中间件没拦住未登录请求、跨域头没加、日志没记录。查日志、打 dump 都没用,因为类根本没被实例化。
- 必须在中间件文件开头
use think\contract\MiddlewareInterface; - 类定义改为
class Auth implements MiddlewareInterface -
handle()方法签名强制为public function handle($request, \Closure $next): \think\Response - 返回值漏写
\think\Response类型提示,PHP 8.1+ 会抛TypeError,TP8 不兜底
全局中间件注册只认 ::class 常量,不认字符串
TP8 的容器反射机制依赖类的完整 FQCN(全限定类名),app/middleware.php 返回的数组里若写 'app\middleware\Auth',框架会尝试在当前命名空间下解析,结果是 app\middleware\app\middleware\Auth,必然报错或静默忽略。
这个行为和 TP6 兼容但更严格:TP6 有时能“猜对”,TP8 绝对不猜。
- 必须写
\app\middleware\Auth::class(带反斜杠前缀) - 禁止在
app/middleware.php中使用use语句——该文件被当作纯配置脚本加载,use被 PHP 忽略 - 如果中间件在子应用里(如
app/admin/middleware/Log.php),它的命名空间必须是app\admin\middleware,且注册时写\app\admin\middleware\Log::class
多应用下中间件不能跨应用共享容器实例
TP6 的多应用本质是多个独立 thinkApp 实例共用内核,TP8 虽移除 multi-app 模式,但若你仍在 TP6 多应用结构上升级到 TP8,要注意:每个子应用(如 admin)的容器是隔离的。你在 app/admin/middleware/Auth.php 里调用 app('cache'),拿到的是 admin 应用上下文下的缓存实例,和 index 应用的缓存配置、生命周期完全无关。
典型踩坑点:想在 admin 中间件里复用 index 的 JWT 解析服务,直接 app('index')->make(JwtService::class) 会失败——app('index') 在 TP8 已不存在,thinkApp 类本身也被废弃。
- 跨应用逻辑必须走 API、消息队列或统一配置中心,不能靠容器直取
- 数据库连接、Redis 实例等基础服务,需在每个子应用的
config/database.php或config/cache.php中单独配置,别指望“继承主应用” - 如果你强行保留 TP6 多应用目录结构但用 TP8 内核,
app/multi.php文件必须删掉,否则框架仍按单应用初始化,子应用入口文件会被忽略
路由级中间件绑定方式不变,但参数类型更敏感
TP8 下 ->middleware() 的链式调用写法和 TP6 一致,但闭包中间件的参数类型声明成了硬性要求。省略类型提示不只是警告,PHP JIT 编译器可能在运行时崩溃。
比如这段代码在 TP6 可能只警告,在 TP8 会直接中断请求:
Route::get('user', 'User@index')->middleware(function ($request, $next) {
return $next($request);
});
- 必须显式标注参数类型:
function (\think\Request $request, \Closure $next) - 返回值建议也加类型提示:
function (\think\Request $request, \Closure $next): \think\Response - 类中间件绑定仍支持数组形式:
->middleware([\app\middleware\Auth::class, \app\middleware\Log::class]) - 注意:TP8 中
->middleware('auth')这种字符串别名方式已彻底废弃,不会 fallback 到配置映射
php think route:list 确认中间件列在对应路由后面,再手动 curl 测试 OPTIONS 和实际接口响应头。

















