致命影响:前置输出(空格、换行、BOM)会导致HTTP头提前发送,使json()响应体开头混入非法字符,引发“Unexpected token in JSON at position 0”等解析失败。

会,而且是致命影响——只要 json() 之前有任何前置输出(包括空格、换行、BOM),JSON 响应就会损坏,前端解析直接失败。
为什么一个空格就能让 JSON 报错
PHP 的 json_encode() 输出必须是纯 JSON 字符串,开头不能有任何字符。ThinkPHP 的 json() 方法会自动设 Content-Type: application/json,但这个 header 只能在「未输出任何内容」时发送。一旦前面有空格,PHP 就会提前触发 HTTP header 发送,后续再设 Content-Type 就报 headers already sent,最终响应体变成: [空格]{...},JSON 解析器在 position 0 就卡住。
- 常见现象:
Unexpected token in JSON at position 0(那个小方块就是 BOM 或空格) - 浏览器开发者工具里看响应预览是空白,但“Response”标签页能看到开头多出乱码或空行
- Axios 报
SyntaxError: Unexpected token,fetch().json() 直接 reject - Postman 显示 “Could not get any response” 或 raw body 开头有不可见字符
哪些地方容易藏空格或 BOM
不是只有 echo 才危险,这些“安静”的地方更常中招:
- 所有 PHP 文件(尤其是
config/、route/、middleware/、app/下控制器)必须保存为 UTF-8 无 BOM;VS Code 右下角编码显示 “UTF-8” 不够,要确认是 “UTF-8 with UTF-8 BOM” 还是 “UTF-8 without BOM” -
config/app.php或database.php文件末尾多了一个空行或空格 —— 这个空行在框架加载时就被输出了 - 中间件里写了
dump()、trace()或未捕获的 Notice(比如访问$data['missing']),即使没echo,调试信息也会提前刷到输出流 - 路由闭包或事件监听器里写了
var_dump(),哪怕加了@也拦不住输出
怎么快速定位和修复
别靠肉眼找空格,用工具+验证组合拳:
立即学习“PHP免费学习笔记(深入)”;
- 用命令行检查 BOM:
xxd your_file.php | head -n1,看到00000000: efbb bf就说明有 BOM,用编辑器转存为无 BOM - 在控制器最开头加一行:
if (headers_sent($file, $line)) { throw new \Exception("Headers already sent in {$file} on line {$line}"); },立刻暴露哪行先输出了 - 临时关闭调试模式(
app_debug = false),排除 Trace 和日志干扰;再开,看是否恢复正常 - 用
curl -v http://your-api直接看原始响应头和 body 开头几个字节,比浏览器更干净
真正麻烦的不是空格本身,而是它藏得深、报错位置和实际出问题的文件往往不一致——可能你在控制器写了 json(),但崩掉的原因是 config/route.php 末尾多了一行空格。每次改完配置或引入新文件,都要重新过一遍编码和空白检查。



















