使用Open trivia DB API与PHP开发测验应用的答案校验问题
问题
我正在使用Open Trivia DB API和PHP开发一款测验Web应用,当前遇到的问题是校验用户所选选项是否为正确答案时,程序每次提交请求都会重新调用API获取完全不同的题目集,导致用于校验的题目与用户作答的题目完全不符。请问如何存储首次API调用的结果,并用其来校验用户选项,而非每次重新调用API?
控制器代码
public function callAPI($method, $url, $data){ $curl = curl_init(); switch ($method){ case "POST": curl_setopt($curl, CURLOPT_POST, 1); if ($data) curl_setopt($curl, CURLOPT_POSTFIELDS, $data); break; case "PUT": curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT"); if ($data) curl_setopt($curl, CURLOPT_POSTFIELDS, $data); break; default: if ($data) $url = sprintf("%s?%s", $url, http_build_query($data)); } curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HTTPHEADER, array( 'APIKEY:xxxxxx', 'Content-Type: application/json', )); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); $result = curl_exec($curl); if(!$result){die("Connection Failure");} curl_close($curl); return $result; } public function quiz() { $get_data= $this->callAPI('GET', 'https://opentdb.com/api.php?amount=10&category=18', false); $data = json_decode($get_data, true); if($_SERVER["REQUEST_METHOD"]=="POST") { $sum = 0; foreach ($data as $key => $value) { foreach ($value as $key => $k) { if($_POST[$key]== $k['correct_answer']) { $sum++; } echo"The question is ".$k['question']."you answered $_POST[$key] and the correct answer is ". $k['correct_answer']. " Your score is $sum"; // 用来排查问题的输出 } } } else { $this->view('quiz', $data); } }
视图代码
<div class="col-md-6 grid-margin stretch-card "> <form class="my-auto" id ="regForm" method="POST" action=""> <div class="card"> <div class="card-body"> <?php foreach ($data as $key => $value): foreach ($value as $key => $k):?> <div class="tab"> <span><p><?php echo $key+1 ?></p></span> <h4 class="card-title"> <?php echo $k["question"] . "<br>";?></h4> <?php foreach ( $k["incorrect_answers"] as $incorrect): ?> <div class="form-check"> <label class="form-check-label" for="radio1"></label> <input type="radio" class="form-check-input" id="radio1" name="<?php echo $key ?>" value="<?php echo " $incorrect"; ?>"> <?php echo " $incorrect"; ?> </div> <?php endforeach ?> <input type="radio" class="form-check-input" id="rad2" name="<?php echo "$key" ?>" value="<?php echo $k["correct_answer"]; ?>"> <?php echo $k["correct_answer"]; ?> <div style="overflow:auto;"> <div style="float:right;"> <button type="button" class="btn btn-outline-danger btn-fw" id="prevBtn" onclick="nextPrev(-1)">Previous</button> <button type="button"class="btn btn-outline-primary btn-fw" id="nextBtn" onclick="nextPrev(1)">Next</button> </div> </div> </div> <?php endforeach ?> <?php endforeach ?> </div>
解决方案
核心思路是将首次获取的题目数据存储到用户Session中,这样在POST提交校验时,直接从Session读取之前的题目,而非重新调用API。
步骤1:初始化Session
在控制器的quiz方法开头启动Session,确保Session可用:
public function quiz() { session_start(); // 启动Session // 后续代码... }
步骤2:修改题目获取与校验逻辑
只有当Session中没有存储题目时,才调用API获取新题目;校验时直接读取Session中的数据:
public function quiz() { session_start(); // 检查Session中是否已有题目数据 if (!isset($_SESSION['quiz_questions'])) { $get_data= $this->callAPI('GET', 'https://opentdb.com/api.php?amount=10&category=18', false); $_SESSION['quiz_questions'] = json_decode($get_data, true); } $data = $_SESSION['quiz_questions']; // 从Session读取题目 if($_SERVER["REQUEST_METHOD"]=="POST") { $sum = 0; foreach ($data as $key => $value) { foreach ($value as $q_index => $question) { // 严格比对答案,同时处理可能的空格问题 if(isset($_POST[$q_index]) && trim($_POST[$q_index]) === trim($question['correct_answer'])) { $sum++; } echo "题目:".$question['question']."<br>你的答案:".$_POST[$q_index]."<br>正确答案:".$question['correct_answer']."<br>当前得分:$sum<br><br>"; } } // 校验完成后清空Session,避免重复使用同一套题目 unset($_SESSION['quiz_questions']); } else { $this->view('quiz', $data); } }
步骤3:视图代码优化
修正单选框的id唯一性问题,同时去掉选项输出时的多余空格,避免答案比对失败:
<!-- 修正错误选项的输出,去掉多余空格并设置唯一ID --> <?php $incorrect_index = 0; ?> <?php foreach ( $k["incorrect_answers"] as $incorrect): ?> <div class="form-check"> <label class="form-check-label" for="radio_<?php echo $key.'_'.$incorrect_index; ?>"></label> <input type="radio" class="form-check-input" id="radio_<?php echo $key.'_'.$incorrect_index; ?>" name="<?php echo $key ?>" value="<?php echo htmlspecialchars($incorrect); ?>"> <?php echo htmlspecialchars($incorrect); ?> </div> <?php $incorrect_index++; ?> <?php endforeach ?> <!-- 修正正确答案的输出,设置唯一ID --> <input type="radio" class="form-check-input" id="rad2_<?php echo $key; ?>" name="<?php echo $key ?>" value="<?php echo htmlspecialchars($k["correct_answer"]); ?>"> <?php echo htmlspecialchars($k["correct_answer"]); ?>
关键注意点
- Session依赖Cookie,需确保用户浏览器允许Cookie;
- 校验完成后清空Session,避免用户刷新页面重复使用同一套题目;
- 使用
trim()处理答案前后空格,用===严格比对,避免匹配错误; - 用
htmlspecialchars()转义题目和选项内容,防止XSS攻击。
内容的提问来源于stack exchange,提问作者Prisca Chidimma
相关产品推荐
相关产品推荐

