PHP技能测试项目分数计算问题求助:仅正确作答时加分
问题分析与修复方案
看起来你遇到的核心问题是错误答案也会触发分数累加,这大概率是因为答案判断逻辑的漏洞加上潜在的SQL语法/类型问题导致的。咱们一步步拆解修复:
主要问题点
- 不必要的类型转换破坏答案匹配:你把用户提交的选项值
$qVal强制转成了int,如果数据库里的correctanswer是字符串类型(比如选项文本、A/B/C/D这类标识),转换后会直接变成0,导致正确答案永远匹配失败,反而可能因为SQL逻辑的异常触发错误加分。 - SQL注入风险+查询效率低:直接把用户输入拼进SQL语句,不仅有安全风险,还分开执行了两次查询(查正确答案、查 strand),完全可以合并成一次。
- 缺失查询错误处理:只处理了
$result2的错误,没处理$result1的,万一查正确答案的SQL出错,后续逻辑会乱。 - 模糊的正确判断:用
if($row1['rightAnswer'])虽然能判断非0值,但不如明确判断=== 1严谨,避免意外情况。
修复后的results.php代码
<?php if(isset($_POST['submit'])) { $ans = $_POST['ans'] ?? []; // 确保数组存在,避免未定义索引警告 $abmscore = 0; $humssscore = 0; $stemscore = 0; $gasscore = 0; $tvlscore = 0; if(!empty($ans)): // 预处理语句,合并查询,防止SQL注入,提高效率 $stmt = mysqli_prepare($conn, "SELECT correctanswer, strand FROM tquestions WHERE test_id = ?"); mysqli_stmt_bind_param($stmt, "i", $qID); // test_id是整数,用i类型绑定 foreach($ans as $qID => $qVal) { $qID = (int) $qID; // test_id是整数,转换没问题 // 注意:这里不要转$qVal类型,保留原始提交值,和数据库correctanswer类型匹配 // 执行查询获取当前问题的正确答案和所属strand mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); if(!$result) { printf("Error: %s<br>", mysqli_error($conn)); exit(); } $row = mysqli_fetch_array($result, MYSQLI_ASSOC); if(!$row) { // 找不到对应test_id的问题,跳过 continue; } // 判断用户答案是否正确 if($qVal === $row['correctanswer']) { // 根据strand累加分数 switch($row['strand']) { case 'ABM': $abmscore++; break; case 'HUMSS': $humssscore++; break; case 'STEM': $stemscore++; break; case 'GAS': $gasscore++; break; case 'TVL': $tvlscore++; break; } } } mysqli_stmt_close($stmt); endif; } ?>
额外需要检查的点
test.php的选项值匹配:确保你在test.php中输出的radio按钮value和数据库correctanswer字段的内容完全一致。比如:- 如果数据库
correctanswer存的是选项标识(如'A'/'B'),那test.php里的value应该输出标识,而不是选项文本:// 假设数据库里有对应选项标识的字段,比如correctanswer='A' <input type="radio" name="ans[<?php echo $test_id;?>]" value="A"><?php echo $optiona;?> - 如果存的是选项文本,那当前的value写法没问题,但要确保文本完全一致(包括空格、大小写)。
- 如果数据库
数据库字段类型:确认
tquestions表的correctanswer字段类型和用户提交的value类型匹配,比如都是VARCHAR或都是INT,避免类型不匹配导致的判断失败。
为什么这样修复?
- 用预处理语句彻底解决SQL注入问题,同时避免手动拼接SQL的语法错误。
- 合并两次查询为一次,减少数据库交互,提升性能。
- 去掉了破坏答案匹配的
$qVal = (int) $qVal,保留原始提交值和数据库直接比对。 - 用
switch替代多个elseif,代码更简洁易维护。 - 增加了对找不到问题的处理,避免无意义的逻辑执行。
内容的提问来源于stack exchange,提问作者Dizza
相关产品推荐
相关产品推荐

