thinkphp 5.x 中间件无法动态扩展,只能新建类、按顺序注册或调用独立服务;必须在 app/middleware.php 全局注册(返回数组)、路由级链式 middleware() 或控制器构造函数中注册;handle() 参数需严格匹配,$request->post() 等不可重放,session 需在 sessioninit 后才可用。

中间件函数不能“扩展”,只能按规范重写或组合
ThinkPHP 5.x 没有提供类似 extend() 或 registerFunction() 这样的中间件函数扩展机制。所谓“扩展中间件函数”,实际是误读——你无法给已有的 handle() 方法动态加逻辑,只能通过以下方式实现功能叠加:
- 新建一个中间件类,在
handle()中调用其他服务、工具函数或静态方法(比如权限校验逻辑抽成Auth::check()) - 把多个中间件按顺序注册(如
['Auth', 'Log', 'RateLimit']),靠执行链传递请求/响应 - 在中间件内使用
app('cache')、app('log')等容器服务,避免硬编码依赖
想复用逻辑?别改 handle(),抽离到独立类里
常见错误是把所有判断塞进 handle():查数据库、解析 token、拼 SQL……这导致中间件臃肿难测、无法单元测试。正确做法是把业务逻辑拆出去:
- 新建
app/service/AuthService.php,提供checkToken($token)和getRole($uid) - 中间件里只做胶水工作:
$result = app(AuthService::class)->checkToken($request->header('token')); - 返回拦截响应时用
json(['code' => 401])或redirect('/login'),**不能**用echo或die()
middleware.php 注册错位置,中间件根本不会加载
TP5.1+ 的中间件注册入口只有两个有效位置,其余全是无效的:
- 全局注册:必须放在
app/middleware.php(注意不是config/middleware.php),且文件必须return一个数组,例如:return [\app\middleware\AuthCheck::class]; - 路由级注册:必须链式调用
->middleware(),例如:Route::get('api/user', 'User/index')->middleware(\app\middleware\AuthCheck::class); - 控制器级注册:在控制器构造函数中写
$this->middleware(\app\middleware\AuthCheck::class);,不是protected $middleware属性(那是 TP6 写法,TP5 不认)
常见失效原因:删了 app/middleware.php、文件里写了 echo、返回了 null 或字符串、类名漏了命名空间反斜杠。
传参和生命周期问题最容易踩坑
中间件看似简单,但参数读取和执行时机非常敏感:
-
$request->param()安全,可多次调用;$request->post()或$request->input()只能读一次,后续为空——POST body 被框架消费后不可重放 - Session 在
SessionInit中间件之后才可用,如果你的中间件排在它前面(比如放在app/middleware.php数组开头),$request->session()会返回空 - 需要传额外参数(如角色名)?注册时写
->middleware(\app\middleware\AuthCheck::class, 'admin'),然后handle()签名改成handle($request, \Closure $next, $role)
真正难的从来不是写个 handle(),而是理清请求流经哪几个中间件、每个阶段能访问什么、哪些数据已被消费、哪些服务尚未初始化——这些细节不画图推演一遍,光靠试错很难定位静默失败。











