ThinkPHP 6 需手动解析 PUT/DELETE 请求体:根据真实请求方法和 Content-Type,用 file_get_contents('php://input') 分别处理 application/json 或 application/x-www-form-urlencoded 数据,不可依赖 $request->post() 或伪方法 $request->put()。

ThinkPHP 6 如何正确接收 PUT/DELETE 请求体参数
ThinkPHP 6 默认不自动解析 PUT、DELETE 等非 GET/POST 请求的原始请求体(php://input),直接调用 $request->post() 或 $request->param() 会返回空数组——这不是你写错了,是框架默认行为。
根本原因是:TP6 的 Request 类只对 POST 方法自动解析 application/x-www-form-urlencoded 和 multipart/form-data,而 PUT/DELETE 不触发该逻辑,即使 Content-Type 是表单类型。
- 必须手动读取并解析
php://input(注意:仅当Content-Type是application/x-www-form-urlencoded或application/json时才有效) - 若前端用
fetch发送PUT且 body 是URLSearchParams,后端需显式解析;若发的是 JSON,要用json_decode(file_get_contents('php://input'), true) -
$request->put()和$request->delete()是伪方法,实际不存在——TP6 没提供原生的put()成员函数
兼容所有请求方法:统一用 input() + 手动解析
最稳的做法是绕过 post(),直接处理原始输入。TP6 的 $request->input() 支持指定方法和解析方式,但要注意它默认只对 POST 生效,所以得配合 php://input 自行判断。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 先用
$method = $request->method(true)获取真实请求方法(忽略_method伪装) - 若方法是
PUT或DELETE,且Content-Type包含application/x-www-form-urlencoded,用parse_str(file_get_contents('php://input'), $data) - 若
Content-Type是application/json,一律走json_decode(file_get_contents('php://input'), true) ?: [] - 别依赖
$request->only()直接传参,它底层仍走post()分支
示例片段:
if (in_array($request->method(true), ['PUT', 'DELETE'])) {
$raw = file_get_contents('php://input');
if (stripos($request->header('content-type'), 'application/json') !== false) {
$params = json_decode($raw, true) ?: [];
} else {
parse_str($raw, $params);
}
} else {
$params = $request->param();
}
为什么不能只靠 _method=PUT 伪装?
很多前端用 POST + _method=PUT 绕过浏览器限制,这确实能让 TP6 走进 PUT 路由,但参数仍然从 $_POST 读取——而 $_POST 只有在 Content-Type: application/x-www-form-urlencoded 且请求方法为 POST 时才被 PHP 自动填充。
这意味着:
- 如果用
fetch发POST+body: JSON.stringify(...)+_method=PUT,$_POST为空,$request->post()也为空 -
_method只影响路由匹配和$request->method()返回值,不影响参数来源 - 真正要兼容,就得区分「真实方法」和「参数载体」,不能假设
_method改变了数据解析路径
Form 表单提交 PUT/DELETE 的坑:浏览器根本不支持
HTML 原生 <form method="PUT"> 会被浏览器强制转成 GET 或 POST,这是规范限制。所以你在模板里写 method="PUT",实际发出的仍是 POST 请求。
因此:
- 不要指望表单直接发
PUT,必须用 JS(fetch/Axios) - 若坚持用表单,必须配合
_method=PUT+enctype="application/x-www-form-urlencoded",且后端要主动检查$_POST['_method']并切换解析逻辑 - TP6 的
think\facade\Request::method()默认开启var_method配置(读_method),但参数还是得按真实请求体处理,这点极易混淆
真实参数流向永远取决于:HTTP 方法 + Content-Type + PHP 的 php://input 可读性,而不是路由定义或 _method 字段。



















