ThinkPHP 5.1 的 $request->put() 返回空是因为 PHP 原生不解析 PUT 请求体,$_PUT 不存在;需根据 Content-Type 手动读取 php://input 并解析 JSON 或表单数据,同时确保 Web 服务器与路由支持 PUT 方法。

ThinkPHP 5.1 默认不自动解析 PUT 请求体,直接调用 $request->put() 会返回空数组,必须手动处理 php://input 流才能拿到参数。
为什么 $request->put() 拿不到数据?
因为 PHP 的 $_PUT 超全局变量根本不存在,框架的 put() 方法依赖底层是否已解析原始请求体。而 Apache/Nginx 默认只对 POST 做 application/x-www-form-urlencoded 或 multipart/form-data 解析,PUT 请求的 body 不会被自动注入到任何超全局变量中。
常见错误现象:$request->put('id') 返回 null,$request->param('id') 也为空,但用 Postman 发送 PUT 时明明带了 {"id":123} 或 id=123。
- PUT 请求体类型决定解析方式:如果是
application/json,需json_decode(file_get_contents('php://input'), true) - 如果是
application/x-www-form-urlencoded,需parse_str(file_get_contents('php://input'), $data) - ThinkPHP 的
$request->put()仅在你提前调用过$request->put($data)手动注入后才有效
如何正确接收 application/json 类型的 PUT 参数
这是 RESTful 接口最常用的 PUT 场景,比如更新用户资料。不能依赖 input('put.id') 或 $request->post('id'),它们都失效。
立即学习“PHP免费学习笔记(深入)”;
实操建议:
- 先判断请求方法:
if ($request->isPut()) { ... } - 读取原始输入:
$raw = file_get_contents('php://input'); - 安全解码 JSON:
$data = json_decode($raw, true) ?: [];(加?: []防止null导致报错) - 可选:用
$request->put($data)注入后,后续就能用$request->put('name')单字段取值了
示例片段:
public function update($id)
{
$request = request();
if (!$request->isPut()) {
return json(['code' => 405, 'msg' => 'Method not allowed']);
}
$raw = file_get_contents('php://input');
$data = json_decode($raw, true) ?: [];
$name = $data['name'] ?? '';
// 后续业务逻辑...
}
如何兼容 application/x-www-form-urlencoded 的 PUT 表单
部分前端库(如旧版 Axios)或测试工具可能以表单格式发 PUT,此时不能当 JSON 解析,否则得到 null。
关键点:
- 检查
Content-Type头:$request->header('content-type') - 若匹配
application/x-www-form-urlencoded,用parse_str()解析 - 避免直接
file_get_contents('php://input')后硬 JSON 解,否则会崩 - ThinkPHP 的
$request->param()对这种 PUT 表单完全无效,别试
简写判断逻辑:
$contentType = strtolower($request->header('content-type'));
if (strpos($contentType, 'application/x-www-form-urlencoded') !== false) {
parse_str(file_get_contents('php://input'), $data);
} elseif (strpos($contentType, 'application/json') !== false) {
$data = json_decode(file_get_contents('php://input'), true) ?: [];
} else {
$data = [];
}
容易被忽略的坑:Nginx/Apache 配置与路由限制
即使代码写对,也可能 405 Method Not Allowed —— 这不是 TP 的问题,是 Web 服务器拦截了 PUT。
排查顺序:
- Nginx:确认没禁用
limit_except,或显式放开PUT,例如:limit_except GET HEAD POST PUT DELETE { allow all; } - Apache:确保
mod_rewrite正常,且 .htaccess 没用Deny from all拦掉非 GET/POST - ThinkPHP 路由:RESTful 路由需显式声明,比如
Route::put('user/:id', 'User/update');,不能只写get或post - CSRF:TP5.1 默认开启 CSRF 验证,而 PUT 请求通常不带 token,需在控制器或中间件中关闭:
protected $middleware = ['csrf' => false];
真正麻烦的从来不是“怎么写”,而是“为什么写了却没进方法”——先查 Nginx 错误日志,再看 TP 日志里的 method 是否为 PUT,最后才动代码。



















