Http.post从PHP取数据存入SharedPreferences后取值为null问题排查
问题排查与解决方案
首先,我们来一步步拆解你遇到的问题:数据库插入成功说明PHP端的核心逻辑没问题,但Dart端存SharedPreferences后跳转取到null,大概率是异步流程顺序问题或者PHP端返回数据的潜在漏洞,下面分点分析并给出修复方案:
一、先修复PHP端的逻辑漏洞
你的PHP代码里有个关键判断错误:isset($query)无法准确判断查询是否获取到有效数据。因为mysqli_query即使查询不到任何结果,也会返回一个空的结果集对象(不会是false),只有SQL语法错误或连接失败时才会返回false。这会导致当bookingID不存在时,$order = mysqli_fetch_array($query)得到null,此时$order['orderID']会触发PHP警告,甚至可能让返回的response['id']为null,直接导致Dart端拿到无效值。
修复后的PHP代码
include "conn.php"; $response = array(); $name = $_POST['name']; $age = $_POST['age']; $bookingID = $_POST['id']; // 先判断查询是否执行成功,且是否有结果 $query = mysqli_query($connect, "SELECT orderID FROM tb_order WHERE bookingID = '$bookingID' "); if ($query && mysqli_num_rows($query) > 0) { $order = mysqli_fetch_array($query); $queryResult = $connect->query("INSERT INTO tb_nameage (name, age, orderID) VALUES ('$name', '$age', '" . $order['orderID'] . "') "); $response['id'] = $order['orderID']; echo json_encode($response); } else { $response['message'] = "Failed to find matching orderID or query error"; echo json_encode($response); }
额外提醒:你的代码存在SQL注入风险,建议使用预处理语句替代直接拼接SQL,比如:
$stmt = $connect->prepare("SELECT orderID FROM tb_order WHERE bookingID = ?"); $stmt->bind_param("s", $bookingID); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { $order = $result->fetch_assoc(); // 插入操作同样使用预处理 $stmtInsert = $connect->prepare("INSERT INTO tb_nameage (name, age, orderID) VALUES (?, ?, ?)"); $stmtInsert->bind_param("sis", $name, $age, $order['orderID']); $stmtInsert->execute(); $response['id'] = $order['orderID']; echo json_encode($response); }
二、修复Dart端的异步流程问题
你的Dart代码有两个核心问题:
setState误用:orderID是数据变量,不需要用setState赋值(setState是用来触发UI重绘的),直接赋值即可,避免不必要的状态更新混淆。- 跳转时机未等待异步操作完成:点击按钮后直接跳转,可能发生在
SharedPreferences存值完成之前,导致第二个页面读取到旧的null值。
修复后的Dart代码
// 确保所有异步操作完成后再跳转 delayedSend() async{ await inputData(); // 等待接口请求并拿到orderID await getID(); // 等待SharedPreferences存值完成 // 在这里执行页面跳转 Navigator.push(context, MaterialPageRoute(builder: (context) => SecondPage())); } inputData() async{ var url = "http://ip/apts/addNameAge.php"; var respon = await http.post(url, body: { "name": name, "age": age, "id" : bookingID }); var datauser = json.decode(respon.body); // 直接赋值,无需setState orderID = datauser['id']; // 调试用:打印接口返回数据,确认是否拿到有效orderID print("PHP返回的orderID: $orderID"); } getID() async{ SharedPreferences preferences = await SharedPreferences.getInstance(); // 直接存值,无需setState,加默认值避免null报错 await preferences.setString('orderID', orderID ?? ""); }
三、额外调试建议
- 在Dart的
inputData中打印respon.body,确认PHP返回的JSON格式是否正确,是否包含有效的id字段。 - 在第二个页面读取SharedPreferences时添加调试打印:
// 第二个页面的初始化逻辑 getSavedOrderID() async{ SharedPreferences preferences = await SharedPreferences.getInstance(); String? savedID = preferences.getString('orderID'); print("从SharedPreferences读取的orderID: $savedID"); }
通过这些调试信息,可以快速定位问题出在接口返回、本地存值还是跳转时机上。
内容的提问来源于stack exchange,提问作者Maruzi Muslih
相关产品推荐
相关产品推荐

