PHP+MySQL随机抽题问答系统开发:答案存储与题目切换问题求助
解决PHP问答系统状态丢失与答案存储问题
我之前也碰到过完全一样的问题——HTTP是无状态的,每次点击提交按钮都会让PHP重新运行一遍脚本,你之前定义的$draw_q_ID、$index这些局部变量根本没法跨请求保存。要解决这个问题,核心就是用PHP Session来存储需要跨请求保留的数据:已抽取的题目ID列表、用户的答案数组、当前答题的索引。下面是具体的改造步骤:
第一步:全局启用Session
在所有涉及状态保存的PHP文件最顶部添加session_start();,比如index.php和quiz.php的开头(必须在输出任何HTML内容之前调用,否则会报header already sent错误):
<?php session_start(); ?> <!doctype html> <head></head> <!-- 后续内容不变 -->
第二步:修改题目抽取逻辑,仅在启动时生成10道题
原来的DrawQuestion()生成30道题,我们只需要10道,而且要确保只在用户第一次点击START时生成,之后复用这个列表。修改quiz.php里的start分支:
case 'start': // 初始化Session中的答题状态 $_SESSION['drawn_questions'] = array_slice(DrawQuestion(), 0, 10); // 取前10道不重复题目 $_SESSION['user_answers'] = []; // 存储用户答案的关联数组(键:题目ID,值:用户选择) $_SESSION['current_index'] = 0; // 当前答题的索引 // 获取第一道题 $current_q_id = $_SESSION['drawn_questions'][$_SESSION['current_index']]; $drawn_question = PickQuestion($current_q_id); $question = explode(",", $drawn_question); RunQuiz(); break;
第三步:处理答案提交与下一题逻辑
当用户点击A/B选项时,先把当前题的ID和用户选择存入Session,再判断是否已答完10题。修改next分支:
case 'next': // 保存当前题的用户答案 $current_q_id = $_SESSION['drawn_questions'][$_SESSION['current_index']]; $user_choice = $_POST['next-question']; // 统一获取用户选择的值 $_SESSION['user_answers'][$current_q_id] = $user_choice; // 检查是否答完所有题目 $_SESSION['current_index']++; if ($_SESSION['current_index'] >= 10) { ShowResult(); // 展示结果页面 break; } // 获取下一题 $current_q_id = $_SESSION['drawn_questions'][$_SESSION['current_index']]; $drawn_question = PickQuestion($current_q_id); $question = explode(",", $drawn_question); RunQuiz(); break;
第四步:新增结果展示函数
当用户完成10题后,根据存储的答案查询数据库中的祝贺信息:
function ShowResult() { $user_answers = $_SESSION['user_answers']; // 格式化答案数组为SQL IN语句可用的格式 $answer_values = implode("','", array_values($user_answers)); $answer_values = "'$answer_values'"; // 查询祝贺信息(请根据你的表结构调整字段和表名) require '../config/db_connection.php'; $db = getConnection(); $stmt = $db->prepare("SELECT congratulation_text FROM congratulations WHERE answer IN ($answer_values)"); $stmt->execute(); $congratulatory_messages = $stmt->fetchAll(PDO::FETCH_COLUMN); // 渲染结果页面 ?> <div class="quiz-result"> <h2>恭喜你完成所有题目!</h2> <div class="messages"> <?php foreach ($congratulatory_messages as $msg): ?> <p><?php echo htmlspecialchars($msg); ?></p> <?php endforeach; ?> </div> <form method="POST" action=""> <input type="submit" name="start-quiz" value="重新开始"> </form> </div> <?php // 清空Session状态,方便重新开始 unset($_SESSION['drawn_questions'], $_SESSION['user_answers'], $_SESSION['current_index']); }
第五步:调整表单提交按钮的命名
把RunQuiz()里的两个提交按钮的name统一为next-question,这样就能统一获取用户选择的值:
<input type='submit' id='next-question_a' name='next-question' value='$question[0]' style='color: rgba(0, 0, 0,0)'> <!-- ... --> <input type='submit' id='next-question_b' name='next-question' value='$question[2]' style='color: rgba(0, 0, 0,0)'>
额外安全优化:修复SQL注入风险
原来的PickQuestion()直接拼接SQL存在注入风险,修改为PDO预处理语句:
function PickQuestion($q_ID){ require '../config/db_connection.php'; $quiz = "SELECT d_a, d_a_image, d_b, d_b_image FROM `quiz` WHERE `d_id` = ?"; $db = getConnection(); $stmt = $db->prepare($quiz); $stmt->execute([$q_ID]); $row_quiz = $stmt->fetch(); if (!$row_quiz) return ""; // 处理题目不存在的情况 return implode(",", $row_quiz); // 直接用implode简化拼接 }
内容的提问来源于stack exchange,提问作者Eisenheim
相关产品推荐
相关产品推荐

