跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

ThinkPHP控制器怎么接收原始POST_ThinkPHP非表单数据解析介绍【介绍】

ThinkPHP控制器需用file_get_contents('php://input')读取JSON等非表单POST数据,因$request->post()仅支持application/x-www-form-urlencoded和multipart/form-data;Swoole环境推荐$request->getContent()。 ThinkPHP控制器接收原始POST数据,不能只依赖
$this->request->post()
input('post.')
—— 这些方法只解析
Content-Type: application/x-www-form-urlencoded
multipart/form-data
类型的数据,对 JSON、XML、纯文本或自定义二进制 payload 会直接返回空数组。 为什么
$this->request->post()
拿不到 JSON 数据 ThinkPHP 的
Request::post()
内部调用的是 PHP 的
$_POST
超全局变量,而
$_POST
只在请求头为
application/x-www-form-urlencoded
multipart/form-data
时由 PHP 自动解析填充。当前端发来
Content-Type: application/json
时,PHP 不解析,
$_POST
为空,框架自然也读不到。 现象:前端用
fetch({ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({a:1}) })
,后端
$this->request->post()
返回
[]
验证方式:打印
$this->request->header('content-type')
,确认是否为
application/json
或其他非表单类型 正确做法:跳过框架解析层,直接读取原始输入流 用
file_get_contents('php://input')
读原始数据 这是最通用、兼容性最好的方式,适用于 JSON、XML、YAML、Protobuf 等任意非表单格式的 POST 数据(但不支持
multipart/form-data
)。
php://input
是只读流,只能读一次;若你已在框架中触发过
$this->request->param()
$this->request->post()
,可能已被消耗,需在控制器方法开头立即读取 示例代码:
$raw = file_get_contents('php://input'); if (empty($raw)) { throw new \think\Exception('Empty raw POST data'); } $data = json_decode($raw, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new \think\Exception('Invalid JSON format'); }
注意:
php://input
enctype="multipart/form-data"
场景下不可用,此时应改用
$_FILES
+
$_POST
组合处理 不同 Content-Type 下该选哪种方式 别硬套一种写法,必须根据请求头动态适配: PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载 立即学习 “ PHP免费学习笔记(深入) ”;
application/x-www-form-urlencoded
→ 用
$this->request->post('key')
input('post.key')
,安全且带自动过滤
application/json
→ 必须用
file_get_contents('php://input')
+
json_decode()
,别试图用
$this->request->param()
强转
text/xml
application/soap+xml
→ 同样走
php://input
,再用
simplexml_load_string()
解析
application/octet-stream
(如上传二进制文件)→
php://input
直接保存,或配合
stream_copy_to_stream()
流式写入 混合场景(比如同时传 JSON body + query 参数)→
$this->request->get()
拿 query,
php://input
拿 body,不要混用 容易被忽略的坑:Swoole / Swoft / RoadRunner 环境下
php://input
失效 在常驻内存的协程服务器(如 Swoole)中,
php://input
可能被提前读取或不可用,尤其在启用
enable_static_handler
或中间件已消费流时。 解决方案:优先使用
$this->request->getContent()
(ThinkPHP 6+ 支持),它封装了对不同 SAPI 的兼容读取逻辑 TP6 示例:
$raw = $this->request->getContent();
,比手写
php://input
更可靠 若用 TP5.1,可加一层 fallback:
file_get_contents('php://input') ?: ($GLOBALS['HTTP_RAW_POST_DATA'] ?? '')
,但后者需 php .ini 开启
always_populate_raw_post_data
(已废弃,不推荐) 调试建议:在控制器开头加
var_dump($GLOBALS['HTTP_RAW_POST_DATA'], file_get_contents('php://input'), $this->request->getContent());
对比三者输出

相关文章