必须用 file_get_contents('php://input') 读取原始 json 数据,因 application/json 不触发 $_post 解析;需 trim 并去 bom 后 json_decode($raw, true),且前端须设 content-type: application/json。

PHP 用 file_get_contents('php://input') 读原始 JSON
前端发来的 JSON 数据,如果 Content-Type 是 application/json,PHP 不会自动解析进 $_POST 或 $_GET——它根本不会被 PHP 解析成数组。这时候必须手动读取原始请求体。
常见错误现象:$_POST 为空、json_decode($_POST) 报错、json_last_error() 返回 JSON_ERROR_SYNTAX(其实压根没拿到 JSON 字符串)。
- 必须用
file_get_contents('php://input')获取原始 body,这是唯一可靠方式 -
php://input只能读一次,后续再调用返回空字符串 - 不能和
enctype="multipart/form-data"共存,上传文件时该流不可用 - 示例:
$raw = file_get_contents('php://input');<br>$data = json_decode($raw, true);<br>if (json_last_error() !== JSON_ERROR_NONE) {<br> http_response_code(400);<br> exit('Invalid JSON');<br>}
json_decode() 的第二个参数一定要设为 true
不加 true,json_decode() 默认返回 stdClass 对象,后续访问字段得用 ->,但多数业务逻辑习惯用数组下标(['key']),混用极易出 Notice 或 Fatal Error。
使用场景:你打算用 $data['user_id'] 这种写法,就绝不能漏掉 true;若明确要对象且统一用 ->,可不加,但团队协作中几乎没人这么干。
立即学习“PHP免费学习笔记(深入)”;
- 漏掉
true后,isset($data['name'])永远为 false -
foreach ($data as $k => $v)在对象上也能运行,但语义模糊,容易误判结构 - 性能差异极小,别信“对象更快”的说法——实际差异在纳秒级,可忽略
前端发错 Content-Type 导致 PHP 完全收不到数据
很多前端同学用 fetch 发 JSON 却忘了设 header,或者用 jQuery 的 $.ajax 但没关 processData 和 contentType,结果数据被当成表单提交,PHP 把 JSON 字符串塞进了 $_POST 的某个 key 里,甚至整个丢进 $_POST['undefined'](取决于前端怎么拼)。
典型错误现象:file_get_contents('php://input') 返回空,但 $_POST 里有奇怪的长字符串;或者 var_dump($_POST) 显示一堆键名乱码。
- 前端必须显式设置:
Content-Type: application/json - jQuery 示例:
$.ajax({<br> url: '/api/save',<br> method: 'POST',<br> contentType: 'application/json',<br> processData: false,<br> data: JSON.stringify({id: 123, name: 'test'})<br>}); - fetch 示例:
fetch('/api/save', {<br> method: 'POST',<br> headers: {'Content-Type': 'application/json'},<br> body: JSON.stringify({id: 123, name: 'test'})<br>});
中文字符乱码或 json_decode() 失败的隐藏原因
看起来是 JSON 解析失败,但 json_last_error_msg() 显示 “Syntax error”,实际可能是 UTF-8 BOM、不可见控制字符(比如前端编辑器自动插入的零宽空格)、或换行符混入 JSON 字符串开头/结尾。
这种情况在 Windows 环境编辑 JSON、或从某些 CMS/低代码平台导出数据时高频出现。
- 务必在
json_decode()前 trim 原始字符串:$raw = trim(file_get_contents('php://input')); - 检查 BOM:
if (substr($raw, 0, 3) === "\xEF\xBB\xBF") $raw = substr($raw, 3); - 避免用
mb_convert_encoding()强转编码——JSON 规范只允许 UTF-8,转其他编码反而破坏格式 - 调试技巧:用
bin2hex(substr($raw, 0, 10))看前几个字节是不是预期的 ASCII










