You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 05:31:36