PUT请求被中间件跳过,根本原因是未在对应路由显式绑定中间件:Route::put()或Route::resource()需单独指定middleware;应使用$request->method()=== 'PUT'判断,拦截后须return json()->code(403)或abort(403),避免用die/exit,并排查CORS预检、Nginx拦截及Content-Type缺失问题。

PUT请求被中间件跳过?检查是否绑定了正确路由级中间件
ThinkPHP 默认不会对 PUT 请求做特殊处理,但很多人发现自定义中间件对 PUT 请求不生效,根本原因是:中间件没绑定到对应路由上,或只绑在了 GET/POST 路由里。
全局中间件(app/middleware.php)确实能覆盖所有请求方法,但若你用的是路由分组或单个路由绑定方式,必须显式声明支持 PUT:
Route::put('api/user/{id}', 'Api/UserController@update')->middleware('CheckAuth');- 资源路由默认包含
PUT,但中间件需单独指定:Route::resource('user', 'Api/UserController')->middleware(['CheckAuth'], ['update']); - 若用
Route::any()或Route::match(['PUT', 'PATCH']),中间件必须写在这些方法调用链上,不能只挂在get后面
在中间件里准确识别PUT请求并拦截
不要依赖 $_SERVER['REQUEST_METHOD'] 或原始超全局变量——TP6/8 已封装请求对象,且 CLI、代理、预检请求(OPTIONS)下不可靠。应统一用 $request->method() 判断:
-
if ($request->method() === 'PUT')是最安全的写法 - 若需同时拦截
PUT和PATCH,用in_array($request->method(), ['PUT', 'PATCH']) - 注意:前端发
PUT时若 Content-Type 是application/json,$request->post()可能为空,应改用$request->body()或$request->param()(后者已自动解析 JSON)
PUT请求拦截后返回响应的写法陷阱
拦截 PUT 请求时,常见错误是直接 return json(['code'=>403]) 却没设状态码,导致前端收到 200 响应体却是拒绝逻辑。
立即学习“PHP免费学习笔记(深入)”;
- 正确写法:
return json(['code'=>403, 'msg'=>'Forbidden'])->code(403); - 更推荐用
abort(403):它会触发框架异常处理器,保留日志、不跳过响应生命周期,且兼容 RESTful 规范 - 绝对不要用
die()、exit()或echo + exit,这会导致响应头未发送、中间件链中断、缓存/日志/监控失效
为什么PUT请求有时“看起来没被拦截”?查这几个点
实际调试中,PUT 请求看似绕过中间件,往往不是中间件失效,而是请求根本没走到那里:
- CORS 预检请求(
OPTIONS)先于PUT发出,它不带认证头、无 body,若中间件里写了if (!$request->header('Authorization')) { abort(401); },OPTIONS就会被拦住,导致后续PUT根本发不出 - Nginx 或 CDN 层把
PUT当作非法方法直接 405 拒绝,压根没转发给 PHP —— 查 access.log 确认状态码是不是 405 - 前端用
fetch发PUT但没设Content-Type,TP 默认不解析 body,$request->param()为空,误判为“无效请求”而放行
真正难的不是写拦截逻辑,而是确认请求到底卡在哪一层——先看 Nginx 日志,再看框架中间件 trace 输出,最后才动代码。



















