使用Fetch API向PHP服务器发送POST JSON数据遇阻求助
我来帮你梳理一下你遇到的这些问题的根源,以及对应的解决办法——其实核心在于Fetch API的底层特性和PHP对请求数据的解析规则差异,和jQuery的$.ajax比起来,Fetch确实需要我们手动处理更多细节。
一、为什么远程请求会从POST变成GET?
你后来找到的原因很关键:远程URL必须指定到具体的index.php文件,否则服务器很可能做了重定向(比如通过.htaccess把根路径重定向到index.php)。HTTP协议中,当服务器返回3xx重定向时,浏览器默认会把POST请求转为GET请求来访问新地址,这就导致你看到远程请求变成了GET。所以解决办法就是始终使用完整的脚本路径,避免触发服务器的重定向规则。
二、为什么JSON数据无法通过$_POST获取?
这是PHP的特性决定的:$_POST这个超全局变量只会自动解析**Content-Type为application/x-www-form-urlencoded(表单默认格式)或multipart/form-data(文件上传格式)**的请求数据。而你用Fetch发送JSON字符串时,默认的请求头并没有设置Content-Type: application/json,即使设置了,PHP也不会把JSON数据解析到$_POST里——因为这不在它的自动解析范围内。
而jQuery的$.ajax之所以让你觉得“没有问题”,是因为它默认会帮你做一件事:如果你传入的data是一个对象,它会自动把对象序列化成application/x-www-form-urlencoded格式的字符串,并且自动设置对应的Content-Type头,所以PHP能正常解析到$_POST中。但如果你在$.ajax里手动设置contentType: 'application/json'并发送JSON字符串,你会发现同样需要用php://input来读取数据。
三、最优解决方案
根据你的需求,我推荐两种稳定的方案,你可以根据场景选择:
方案1:发送表单格式数据(兼容$_POST)
如果你希望继续用$_POST直接获取数据,可以把请求数据序列化成application/x-www-form-urlencoded格式,Fetch可以用URLSearchParams来轻松实现:
fetch('www.something.com/test/index.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ test: "toast" }) }) .then(response => response.text()) .then(data => console.log(data));
对应的PHP处理代码就很简单了:
// 不需要额外设置Content-Type,除非你要返回JSON $test = $_POST['test']; echo $test; // 直接输出"toast"
方案2:发送JSON格式数据(RESTful场景更推荐)
如果更倾向于用JSON传输数据,需要手动设置Content-Type请求头,服务器端通过php://input读取原始请求体再解析:
fetch('www.something.com/test/index.php', { method: 'POST', headers: { 'Content-Type': 'application/json', // 必须明确设置这个头 }, body: JSON.stringify({ test: "toast" }) }) .then(response => response.json()) // 直接解析JSON响应 .then(data => console.log(data));
对应的PHP处理代码:
// 设置响应头为JSON格式,方便前端解析 header('Content-Type: application/json'); // 读取原始请求体 $rawRequest = file_get_contents('php://input'); // 解析为关联数组(第二个参数设为true),方便使用 $requestData = json_decode($rawRequest, true); $test = $requestData['test']; // 返回JSON格式的响应 echo json_encode(['received_test' => $test]);
四、关于Fetch API的“缺失”?
其实Fetch并没有缺失功能,它只是更底层、更灵活,不像jQuery那样做了很多封装性的默认行为。jQuery帮你处理了数据序列化、请求头设置等细节,而Fetch把这些控制权交还给了开发者——这意味着你需要明确指定请求的格式和头信息,但同时也能更精准地控制请求的每一个细节。
内容的提问来源于stack exchange,提问作者Andrea

