Ajax星级评分系统无法存储评分数据到数据库问题排查
基于select的Ajax星级评分功能报错修复
报错信息
- 警告:
C:\xampp\htdocs\site\ajax_star_rating.php第6行提示 Undefined array key "s_id"(未定义数组键"s_id") - 致命错误:
Uncaught TypeError: mysqli_fetch_array(): Argument #1 ($result) must be of type mysqli_result, bool given,错误抛出位置为C:\xampp\htdocs\site\ajax_star_rating.php第13行
问题根因
- 前后端POST传参字段名不匹配:前端AJAX提交歌曲ID时使用的字段名是
song_id,后端PHP接收时错误写为$_POST['s_id'],无法获取到歌曲ID参数,触发第一个未定义数组键的警告。 - 后端查询无容错逻辑:歌曲ID参数缺失时拼接出的SQL语句存在语法错误,
mysqli_query()执行失败返回布尔值false,直接传入mysqli_fetch_array()就触发了第二个类型致命错误。 - 其他隐患:代码直接拼接传入参数到SQL语句,存在SQL注入风险;未做参数合法性校验,异常场景下直接抛出致命错误,前端无法接收正常响应。
修复步骤
1. 修正后端参数接收逻辑
打开ajax_star_rating.php,将第6行的参数接收代码修改为和前端传参一致的字段名,同时增加参数存在性校验和类型转换:
// 原错误代码:$song_id = $_POST['s_id']; $song_id = isset($_POST['song_id']) ? intval($_POST['song_id']) : 0; $rating = isset($_POST['rating']) ? intval($_POST['rating']) : 0; // 增加参数合法性校验 if ($song_id <= 0 || $rating < 1 || $rating > 5) { echo json_encode(['numRating' => 0]); exit; }
2. 给数据库查询增加结果校验
所有数据库查询执行后先判断返回结果是否合法,避免SQL执行失败时直接传入fetch函数触发致命错误,修改第一次查询的代码段:
// Check rating inside the table $query = "SELECT COUNT(*) AS countSong FROM ratings WHERE s_id = " . $song_id . " and u_id = " . $user_id; $result = mysqli_query($con, $query); if (!$result) { echo json_encode(['numRating' => 0]); exit; } $getdata = mysqli_fetch_array($result); $count = $getdata['countSong'];
3. 核对前端select标签属性配置
前端JS通过el.$elem.data('id')获取元素自定义id,再按下划线拆分提取歌曲ID,必须保证页面上的星级选择标签结构和JS逻辑匹配,参考结构如下:
<select id="star_rating_<?php echo $song_id; ?>" class="rating" data-id="star_rating_<?php echo $song_id; ?>" > <option value="1">1星</option> <option value="2">2星</option> <option value="3">3星</option> <option value="4">4星</option> <option value="5">5星</option> </select> <p>平均评分:<span id="numeric_rating_<?php echo $song_id; ?>"><?php echo $rating; ?></span></p>
调试时可以打开浏览器F12控制台,查看代码中打印的el_id、split_id、song_id三个值是否符合预期,确认拆分得到的歌曲ID正确。
修复后完整后端代码参考
<?php include("registration/connection.php"); $user_id = 1; $song_id = isset($_POST['song_id']) ? intval($_POST['song_id']) : 0; $rating = isset($_POST['rating']) ? intval($_POST['rating']) : 0; if ($song_id <=0 || $rating <1 || $rating>5) { echo json_encode(["numRating" => 0]); exit; } // 检查用户是否已评分 $query = "SELECT COUNT(*) AS countSong FROM ratings WHERE s_id = " . $song_id . " and u_id = " . $user_id; $result = mysqli_query($con, $query); if (!$result) { echo json_encode(["numRating" => 0]); exit; } $getdata = mysqli_fetch_array($result); $count = $getdata['countSong']; if($count == 0){ $insertquery = "INSERT INTO ratings(u_id, s_id, rating) values(". $user_id .", ". $song_id .", ". $rating .")"; mysqli_query($con, $insertquery); }else { $updateRating = "UPDATE ratings SET rating=" . $rating . " where u_id=" . $user_id . " and s_id=" . $song_id; mysqli_query($con, $updateRating); } // 计算平均评分 $query = "SELECT ROUND(AVG(rating),1) as numRating FROM ratings WHERE s_id=".$song_id; $result = mysqli_query($con, $query); $numRating = 0; if ($result) { $getAverage = mysqli_fetch_array($result); $numRating = $getAverage['numRating'] ?? 0; } $return_arr = array("numRating"=>$numRating); echo json_encode($return_arr); ?>
注:当前代码仍使用字符串拼接方式构造SQL,正式环境建议替换为mysqli预处理语句绑定参数,彻底避免SQL注入风险。
内容的提问来源于stack exchange,提问作者F1_lover
相关产品推荐
相关产品推荐

