thinkphp默认不解析put/patch请求体,$request->put()返回空因php无$_put变量,需手动读php://input并按content-type解析json或表单数据,同时确保web服务器放行对应方法且路由显式声明。

ThinkPHP 默认不自动解析 PUT 和 PATCH 请求体,$request->put() 和 $request->patch() 在多数版本中直接调用会返回空数组——这不是你代码写错了,是 PHP 底层和框架设计决定的。
为什么 $request->put() 总是空?
PHP 从不提供 $_PUT 或 $_PATCH 超全局变量,ThinkPHP 的 put() 方法依赖于是否已手动解析 php://input 流并注入数据。Apache/Nginx 默认只对 POST 做表单解析,PUT/PATCH 的请求体(尤其是 JSON)不会被自动填充到任何变量里。
常见错误现象:
-
$request->put('id')返回null -
input('put.id')或$request->param('id')拿不到值 - Postman 发
{"name":"test"},但file_get_contents('php://input')却读到空字符串(说明 Web 服务器拦截了方法)
Web 服务器必须放行 PUT/PATCH 方法
405 Method Not Allowed 错误几乎总是发生在请求根本没进 PHP,而是被 Nginx 或 Apache 拦下了。
实操建议:
- Nginx:检查
limit_except配置,确保包含PUT PATCH,例如:limit_except GET HEAD POST PUT PATCH { deny all; } - Apache:确认启用了
mod_rewrite,并在虚拟主机或.htaccess中允许 PUT,如:<limit put patch></limit>… - 本地开发用
php -S时没问题,上线前务必用curl -X PUT直接测试,绕过前端模拟
如何安全读取并解析 php://input
不能硬写 json_decode(file_get_contents('php://input')) 就完事——不同 Content-Type 必须分路径处理,且 php://input 只能读一次。
实操建议:
- 先判断方法:
if (!$request->isPut() && !$request->isPatch()) { return json(['code' => 405]); } - 读原始流:
$raw = file_get_contents('php://input');(注意:若为空,先查服务器配置) - 按
Content-Type分支解析:
– 若匹配application/json(忽略参数如; charset=utf-8),用json_decode($raw, true) ?: [],并检查json_last_error()
– 若为application/x-www-form-urlencoded,用parse_str($raw, $data)
– 其他类型(如纯文本)按需处理,别盲目 JSON 解 - 可选:注入后复用框架方法:
$request->put($data)(对 PUT)或$request->patch($data)(对 PATCH),之后就能用$request->put('name')单字段取值
路由必须显式声明方法,不能靠控制器判断
ThinkPHP 的安全边界应在路由层,而不是等请求进了控制器再用 $this->request->isPut() 判断。
实操建议:
- 写
Route::put('api/user/:id', 'User/update'),而不是Route::any()或Route::get() - 多个方法允许时传数组:
['method' => ['PUT', 'PATCH']],注意大小写敏感,'put'无效 - 别依赖
_method=PUT表单伪装——ThinkPHP 默认不解析它,除非你在app.php中开启'var_method' => '_method' - RESTful 路由如
Route::resource('user', 'User')生成的 PUT/PATCH 路径,若被其他规则覆盖,要确保 resource() 定义在后面
最易被忽略的一点:ThinkPHP 6.1+ 的 $request->param() 默认只读 POST 类数据(含你手动注入的 PUT/PATCH),不包含 GET 查询参数。如果你习惯用 ?id=123 传 ID,又在控制器里直接 $request->param('id'),升级后就会丢参——得显式用 $request->get('id') 或合并 array_merge($request->get(), $request->post())。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











