中间件不生效主因是未注册、未return或路径/命名空间错误;需确保app/middleware.php存在且返回类名数组,handle()必须返回response实例并调用$next($request)。

中间件不生效,八成是没注册、没 return 或路径/命名空间写错——不是框架问题,是加载链断在了最基础的环节。
中间件类怎么生成和放对位置
用命令行生成最省事,避免手写路径或命名空间出错:php think make:middleware AuthCheck。它会自动建在 app/middleware/AuthCheck.php,类名和文件名严格一致,命名空间固定为 app\middleware。
- 多应用模式(如启用
app/multi_app)下,得手动挪到app/admin/middleware/AuthCheck.php,并把命名空间改成app\admin\middleware - 别放在子目录里,比如
app/middleware/auth/AuthCheck.php,框架压根不扫描 - 文件开头不能有 BOM 头、
echo或注释外的任何输出,否则app/middleware.php加载时可能直接解析失败
handle() 方法必须返回 Response 实例
handle() 是唯一入口,签名必须是 handle($request, \Closure $next),且返回值必须是 think\Response 实例。漏掉 return 或返回 null、string、array,请求就静默中断。
- 放行写法:
return $next($request);—— 这是进入下一层的唯一通道 - 拦截写法:
return json(['code' => 401]);或return redirect('/login');,不能用echo或die('forbidden') - 若需传参(如角色名),路由注册时用
->middleware(\app\middleware\AuthCheck::class, 'admin'),handle()就能多接一个参数:handle($request, \Closure $next, $role)
注册位置错了,中间件根本不会被加载
app/middleware.php 是全局中间件的唯一入口,它必须存在、必须返回数组、数组元素必须是完整类名字符串(带命名空间)。
- 正确示例:
return [\app\middleware\AuthCheck::class];或return ['app\middleware\AuthCheck']; - 常见错误:删了这个文件、改名、写了
echo或return null,导致返回非数组 - 路由级注册必须显式链式调用:
Route::get('user', 'User/index')->middleware(\app\middleware\AuthCheck::class),光写路由定义不加middleware()不会触发 - 控制器级注册写在构造函数:
$this->middleware(\app\middleware\AuthCheck::class);,只对当前控制器方法生效
中间件里读不到 POST 数据或 Session 怎么办
不是 bug,是生命周期顺序问题:POST body 只能读一次,Session 初始化通常在后续中间件才执行。
- 优先用
$request->param()取参数——它内部做了缓存,多次调用安全;$request->post()或$request->input()读一次就空 - 要处理原始 JSON,必须在第一个中间件里用
$request->getContent()读一次,再通过$request->withAttribute('raw_json', $data)存起来,后续中间件用$request->getAttribute('raw_json')取 - Session 尚未启动时,
session('user_id')可能为空;改用think\facade\Session::get('user_id')更稳
最易被忽略的是:app/middleware.php 文件本身的存在性与返回值类型,以及 handle() 中那一行 return $next($request) —— 看似简单,但缺一不可,错一个就整个链路失效。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











