前后端分离后PHP API服务端无法接收$_POST参数问题咨询
核心原因1:POST数据格式不符合PHP自动解析规则
PHP仅会在满足以下两个条件时自动将请求体解析到$_POST全局变量中:
- 请求方法为POST
- 请求头
Content-Type的值为application/x-www-form-urlencoded或multipart/form-data
你当前场景下,前端fetch、axios默认发送JSON格式数据,请求头Content-Type为application/json,不属于PHP自动解析的格式范围,因此$_POST为空数组。你通过file_get_contents('php://input')获取原始请求体的方案是合理的,也是当前前后端分离API开发的通用处理方式。
核心原因2:重写规则配置异常导致$_GET参数丢失
你观测到$_GET仅存在url一项,是因为Apache的重写规则未配置QSA(Query String Append)标志:
常规MVC项目的重写规则默认会将所有请求重写为index.php?url={请求路径},如果不加QSA标志,原请求携带的query参数会被直接覆盖,仅保留重写规则新增的url参数。
修复方法:找到站点根目录的.htaccess文件或Apache虚拟主机配置中的重写规则,在规则末尾追加QSA标志,示例:
# 原规则 RewriteRule ^(.*)$ index.php?url=$1 [L] # 修改后 RewriteRule ^(.*)$ index.php?url=$1 [L,QSA]
补充:你添加的CORS头的作用说明
你在入口添加的头是跨域资源共享(CORS)配置,用于解决前后端不同源(api.loc/exp.loc属于不同域名)的跨域请求限制,和$_POST为空无关联:
Access-Control-Allow-Origin: *:允许所有域名的跨域请求Access-Control-Allow-Methods: POST:允许跨域请求使用POST方法Access-Control-Allow-Credentials: true:允许跨域请求携带Cookie等身份凭证
注意:
Access-Control-Allow-Origin: *和Access-Control-Allow-Credentials: true配置冲突,浏览器会拒绝该跨域配置。如果需要携带凭证,需要将Access-Control-Allow-Origin的值修改为明确的源地址,例如http://exp.loc
可选优化方案
如果希望继续使用$_POST接收参数,可修改前端请求配置:
- 将请求头
Content-Type设置为application/x-www-form-urlencoded - 将提交的JSON数据序列化为URL编码格式,例如axios可配合
qs库处理:
import qs from 'qs' axios.post('/api/xxx', qs.stringify({ foo: 'bar', num: 123 }))
如果要保留JSON传参的通用方式,可在入口文件统一解析请求体供全局使用:
// index.php 入口添加 $_JSON = json_decode(file_get_contents('php://input'), true);
内容的提问来源于stack exchange,提问作者Petar Stoyanov

