php接收ajax的post数据需据content-type选择:application/json用file_get_contents(‘php://input’)解析,urlencoded或form-data才用$_post;返回json必须提前设置header(‘content-type: application/json’);跨域需完整处理options预检及响应头。

PHP接收Ajax的POST数据要检查$_POST还是file_get_contents('php://input')
大多数Ajax请求用fetch或jquery.ajax发application/json时,PHP的$_POST是空的——因为PHP只自动解析application/x-www-form-urlencoded和multipart/form-data这两类编码。JSON数据进的是原始输入流。
判断方法很简单:打印get_headers()里的Content-Type,再看$_POST是否为空。如果前端发的是JSON.stringify({name:'a'}),后端必须用file_get_contents('php://input')读原始体,再json_decode解析。
- 用
$_POST:前端用FormData或$.ajax({data:{key:value}})(默认urlencoded) - 用
file_get_contents('php://input'):前端fetch配headers: {'Content-Type': 'application/json'}且body: JSON.stringify(...) - 别混用:比如
JSON.stringify但又期望$_POST['key']有值,肯定失败
Ajax返回JSON时PHP必须设Content-Type: application/json
前端response.json()会校验响应头,如果PHP没显式设置header('Content-Type: application/json; charset=utf-8'),某些浏览器(尤其旧版safari)会抛Unexpected end of JSON input错误,哪怕内容本身是合法JSON。
常见漏点:echo json_encode(['status'=>'ok'])前没加header(),或者header()写在echo之后(已输出就不能再设头)。
立即学习“PHP免费学习笔记(深入)”;
- 务必在任何
echo/print前调用header() - 避免意外输出:检查PHP文件末尾有没有空行、bom字符,或
require的配置文件末尾多了一个?>换行 - 调试时可用
var_dump(headers_sent())确认头是否已发送
跨域请求失败时别只改access-Control-Allow-Origin
前端报No 'Access-Control-Allow-Origin' header is present,很多人只加header('Access-Control-Allow-Origin: *'),但实际还卡在预检(OPTIONS)上——尤其当Ajax带自定义头(如Authorization)或用PUT/delete方法时。
完整支持需三步:
- 响应预检请求:
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { header('http/1.1 200 OK'); exit; } - 允许方法:
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS') - 允许凭证(如cookies):
header('Access-Control-Allow-Credentials: true'),此时Origin不能为*,得写具体域名
调试Ajax与PHP交互最有效的三件事
别靠猜。90%的“请求没反应”问题,根源在请求发没发出、PHP是否执行、返回内容是否符合预期这三个环节。
- 前端先看Network面板:确认请求URL、method、payload、status code(4xx/5xx直接暴露PHP错误)、Response内容(不是空白或HTML错误页)
- PHP里加
error_log(print_r($_REQUEST, true), 3, '/tmp/ajax-debug.log'),查日志比var_dump可靠,不依赖页面输出 - 临时关闭所有
try/catch和@抑制符,让PHP错误直接报出(开发环境display_errors=On)
异步通信的麻烦在于链条变长了,每个环节都可能断——但只要分段验证,问题从来不在“Ajax难”,而在哪一环被忽略了。