PHP需用file_get_contents('php://input')读取JSON数据并json_decode解析,不可依赖$_POST;须校验Content-Type、检查json_last_error()、避免混用不同数据源。

PHP如何正确读取前端发送的JSON数据
PHP默认不自动解析JSON格式的请求体,$_POST 为空不是代码写错了,而是因为浏览器用 fetch 或 axios 发送 Content-Type: application/json 时,PHP根本不会把数据塞进 $_POST —— 它只处理 application/x-www-form-urlencoded 和 multipart/form-data。
file_get_contents('php://input') 是唯一可靠入口
JSON数据在请求体(body)里,必须手动读取原始输入流:
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
exit('Invalid JSON');
}
-
php://input只能读一次,且不能用于enctype="multipart/form-data"请求 -
json_decode($raw, true)的第二个参数设为true才返回关联数组,否则是对象,后续用$data['key']会报错 - 务必检查
json_last_error(),空字符串、BOM头、中文乱码都会导致解析失败但不报异常
别混淆 $_POST 和 JSON 接收逻辑
同一个PHP脚本不能同时依赖 $_POST 和 php://input 处理不同来源的数据,因为:
- 如果前端用
form.submit()或enctype="application/x-www-form-urlencoded",就该用$_POST - 如果前端用
fetch('/api.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(...) }),就必须走php://input - 混用会导致一个分支永远拿不到数据——比如写了
if (!empty($_POST)) {...} else {...json...},但其实$_POST在JSON请求下天然为空,这个判断看似合理,实则掩盖了接口协议不一致的问题
调试时最容易忽略的三个点
实际部署中出问题,往往卡在这几个细节:
立即学习“PHP免费学习笔记(深入)”;
- 前端没设
Content-Type: application/json,但后端硬按JSON解析——file_get_contents('php://input')能读到数据,但json_decode返回null - Apache + mod_php 环境下,某些配置会过滤掉
php://input流(极少见,但存在),可用var_dump($raw)直接验证是否读到内容 - Vue/React项目常用代理(如 vite.config.js 的
proxy),但代理可能默认不透传Content-Type,导致 PHP 收到的是text/plain类型,JSON 解析静默失败
真正要命的不是语法,是前后端对“这个接口到底接受什么格式”缺乏明确约定。一旦发现 $data 是 null 或空数组,先抓包看 Content-Type 和请求体原文,再查 PHP 是否真读到了字节流。











