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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 21:07:30