request()->put()为空的主因是HTTP请求未按规范发送或服务端未正确解析原始请求体:Content-Type不匹配、php://input被提前读取、Web服务器配置限制(如Nginx未转发PUT体)导致框架无法读取或解析。

ThinkPHP 中 request()->put() 为空的常见原因
直接说结论:request()->put() 没值,绝大多数情况不是框架 bug,而是 HTTP 请求本身没按规范发送 PUT 数据,或者服务端未正确解析原始请求体。ThinkPHP 的 put() 方法依赖 PHP 原生的 php://input 流,而该流只在特定条件下可读且未被消耗。
为什么 php://input 为空或不可用
ThinkPHP 的 put() 底层会尝试读取 php://input 并解析为数组(默认 JSON 或 application/x-www-form-urlencoded)。但以下任一情况都会导致读取失败:
-
Content-Type不是application/json、application/x-www-form-urlencoded或text/xml等 ThinkPHP 支持的类型时,框架跳过解析,返回空数组 - 请求体已被其他代码提前读取(例如手动调用
file_get_contents('php://input')、json_decode(file_get_contents('php://input')),或某些中间件/扩展已消费该流) - Web 服务器配置限制:Nginx 默认不转发
PUT请求体给 PHP-FPM(尤其当client_max_body_size过小或fastcgi_pass_request_body off) - Apache 的
mod_rewrite或mod_security拦截或重写 PUT 请求,导致原始 body 丢失
如何验证和修复 PUT 请求体传递
先绕过框架,直查原始输入是否可达:
file_get_contents('php://input')
在控制器开头加这行并 dump 输出。如果它为空,问题出在传输层;如果不为空但 request()->put() 仍为空,则是解析逻辑未命中。
立即学习“PHP免费学习笔记(深入)”;
- 确保前端发送时设置了正确的
Content-Type,例如:Content-Type: application/json,且请求体是合法 JSON 字符串(如{"name":"test"}) - 避免在任何地方提前读取
php://input—— ThinkPHP 内部只读一次,重复读将返回空字符串 - Nginx 配置中确认没有
fastcgi_pass_request_body off,并检查client_max_body_size是否足够(如设为10m) - 若用 cURL 测试,必须显式传 body:
curl -X PUT http://xxx -H "Content-Type: application/json" -d '{"id":1}',不能只靠-X PUT
替代方案:手动解析 php://input 更可靠
当 request()->put() 不稳定时,直接处理原始输入更可控:
$raw = file_get_contents('php://input');
if (!empty($raw)) {
$data = json_decode($raw, true);
if (json_last_error() === JSON_ERROR_NONE) {
// 成功解析为数组
}
}
注意:request()->param() 在 PUT 请求下默认不合并 php://input,它只处理 URL 查询参数和表单数据;request()->post() 对 PUT 请求无效(它只响应 POST 方法)。
真正容易被忽略的是:很多前端库(如 axios)在发送 PUT 时默认不设 Content-Type,或自动转成 text/plain,这时 ThinkPHP 完全不会尝试解析 —— 必须显式指定且匹配内容格式。



















