中间件不生效主因是handle方法未return $next($request)或注册位置错误;必须有含return $next($request)的handle方法,全局注册需在app/middleware.php返回类名数组,路由/控制器级需正确调用middleware()。

中间件写完不生效?八成是 handle 方法没 return $next($request) 或注册位置错了。
中间件类必须有 handle() 方法且返回 Response
ThinkPHP5 中间件不是普通工具类,它必须实现 handle() 方法,签名固定为 handle($request, \Closure $next)。漏掉 return $next($request) 是最常踩的坑——比如只调用 $next($request); 而没加 return,请求就静默中断,浏览器卡住或返回空页。
所有分支都得显式返回一个 Response 对象:
- 放行时:必须写
return $next($request); - 拦截时:用
return redirect('/login');或return json(['code'=>403]);,不能只echo或abort(403)后不接 return - 第三个参数(如
handle($request, $next, $role))可选,但仅限路由或控制器绑定时传入,全局注册不支持
注册位置错一个字,中间件就完全不加载
app/middleware.php 是 ThinkPHP5 全局中间件唯一入口,它必须存在、必须 return 一个数组、数组元素必须是完整类名(带命名空间)或已配置的别名字符串。
立即学习“PHP免费学习笔记(深入)”;
常见错误:
- 删了
app/middleware.php,或改名为middleware.config.php - 文件里写了
echo 'test';或return null;,导致配置解析失败 - 写成
'Check'却没在config/middleware.php里配别名映射,应写成\app\http\middleware\Check::class - 多应用模式下(
app/multi_app开启),app/middleware.php不起作用,得去对应应用目录(如app/admin/middleware.php)单独配
路由级和控制器级绑定方式完全不同
全局中间件只对整个应用生效,权限类逻辑必须走路由绑定,否则控制器方法根本不会触发。
正确姿势:
- 路由中直接传类名:
Route::get('admin/user', 'Admin/UserController@index')->middleware(\app\http\middleware\Auth::class); - 用别名需先在
config/middleware.php配映射:'auth' => \app\http\middleware\Auth::class,再写->middleware('auth') - 控制器内绑定只对当前控制器有效,且必须在构造函数里:
$this->middleware(\app\http\middleware\Auth::class); - 资源路由(
Route::resource())不会自动继承控制器设置,每个操作(index、store等)要单独指定中间件
中间件里读不到 POST 数据?因为 request-body 只能读一次
如果在中间件里调 $request->post() 或 $request->input() 返回空,大概率是框架自带中间件(如 ValidatePostSize)已经把原始 body 读走了。
安全做法:
- 优先用
$request->param()——它是 ThinkPHP 封装后的缓存访问,多次调用无副作用 - 需要原始 JSON 时,必须在第一个执行的中间件里用
$request->getContent()读一次,再通过$request->withAttribute('raw_json', $data)存起来,后续中间件用$request->getAttribute('raw_json')取 - 避免在多个中间件里反复调
$request->post(),尤其别和日志、验签中间件混用
真正容易被忽略的是中间件执行顺序和返回值约束:return $next($request) 不是可选语法糖,而是框架调度链的硬性契约;而 app/middleware.php 的存在与否,直接决定整个中间件系统是否启动。



















