React向PHP发送POST请求时JSON数据解析异常排查
React+PHP传输数组数据格式错乱修复
问题现象
使用React作为前端框架、PHP作为后端服务,实现前端向PHP端传输选中项数组功能时运行异常:PHP端接收到的POST数据格式错乱,解码后得到格式异常的字符串,无法正确获取前端传递的选中项数组。
问题复现代码
React端原代码
const deleteBtn = async () => { if(selectedProducts.length >= 1){ const sendData = await axios.post("http://localhost/php/index.php",JSON.stringify({ items:selectedProducts // selectedProducts 实际值为 ["GGWP0008","GGWP0009","GGWP0010"] })) } }
PHP端原代码
header('Access-Control-Allow-Origin: http://localhost:3000'); if($_SERVER["REQUEST_METHOD"] === "POST"){ print_r(json_decode($_POST, true)); $_POST = json_decode(array_keys($_POST)[0], true); // 尝试解码传入的JSON请求 print_r($_POST); // 输出格式异常的字符串 }
异常时$_POST打印结果
Array ( [{"items":] => Array ( ["GGWP0008","GGWP0007"] => ) )
故障原因
- 前端请求配置错误:手动调用
JSON.stringify序列化请求数据后,未设置对应的Content-Type: application/json请求头,axios默认将传入的字符串按application/x-www-form-urlencoded表单格式处理,PHP收到请求后也按照表单键值对的拆分规则(按=、&分割内容)解析请求体,完整的JSON字符串被强行拆分,就出现了结构错乱的打印结果。 - PHP端接收逻辑错误:
$_POST超全局变量仅会自动解析application/x-www-form-urlencoded、multipart/form-data两种格式的POST请求,不会自动解析JSON格式的请求体,直接从$_POST中提取内容解码JSON的写法不符合PHP运行逻辑,无法拿到正确数据。
修复方案
两种方案选择其一即可,推荐使用方案1,更符合前后端分离接口的通用交互规范。
方案1:使用JSON格式传输(推荐)
- 修改React端代码:去掉手动的
JSON.stringify调用,直接将待传对象作为参数传给axios.post,axios会自动完成JSON序列化并设置正确的Content-Type请求头:
const deleteBtn = async () => { if(selectedProducts.length >= 1){ // 直接传入对象,无需手动序列化 const sendData = await axios.post("http://localhost/php/index.php", { items: selectedProducts }) } }
- 修改PHP端代码:通过
php://input读取原始请求体,再做JSON解码,不要直接操作$_POST获取JSON数据:
// 跨域配置按需调整 header('Access-Control-Allow-Origin: http://localhost:3000'); header('Access-Control-Allow-Methods: POST'); if($_SERVER["REQUEST_METHOD"] === "POST"){ // 读取原始请求流,解码JSON $rawRequest = file_get_contents('php://input'); $requestData = json_decode($rawRequest, true); // 此时$requestData['items']就是前端传递的选中项数组,可以直接使用 print_r($requestData['items']); }
方案2:使用表单格式传输
如果不需要用JSON格式传参,直接让axios自动将数据转为表单格式即可,PHP端可以直接从$_POST中读取数据:
- React端代码修改:
const deleteBtn = async () => { if(selectedProducts.length >= 1){ const sendData = await axios.post("http://localhost/php/index.php", { items: selectedProducts }, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }) } }
- PHP端代码修改:
header('Access-Control-Allow-Origin: http://localhost:3000'); if($_SERVER["REQUEST_METHOD"] === "POST"){ // 表单格式请求可以直接从$_POST读取,无需额外解码 $selectedItems = $_POST['items']; print_r($selectedItems); }
内容的提问来源于stack exchange,提问作者Mark Wasfy
相关产品推荐
相关产品推荐

