PHP实现单按钮提交多表单:考试系统开发技术问询
嘿,刚接触PHP4个月就能做到这步已经超棒啦!咱们一步步来解决这个单按钮提交所有题目的问题~
先理清当前代码的核心问题
你现在的循环里每个题目都生成了独立的<form>标签,这就导致没法用一个按钮提交所有数据;另外所有题目的单选按钮name都是moznostA,这样选了第二题的选项,第一题的单选会被取消,完全没法区分每个题目的正确答案。
解决方案步骤
1. 重构表单结构:把所有题目放进同一个大表单
修改newTest.php,把外层的<form>放在循环外面,同时给每个题目相关的表单元素加上带序号的name属性,这样PHP接收时能区分不同题目:
<?php $nazovTestu = $_POST['nazovTestu']; $pocetOtazok = $_POST['pocetOtazok']; ?> <!-- 所有题目都放在这个大表单里,提交到专门的存储脚本saveTest.php --> <form action="saveTest.php" method="post"> <!-- 用隐藏域传递考试名称和题目数量,方便后续处理 --> <input type="hidden" name="nazovTestu" value="<?php echo $nazovTestu; ?>"> <input type="hidden" name="pocetOtazok" value="<?php echo $pocetOtazok; ?>"> <?php for($i = 1; $i <= $pocetOtazok; $i++){ echo "<p class='pCenter'> Otazka: $i"; // 给stav函数传题目序号,用来生成唯一的name属性 stav($i); } ?> <!-- 统一的提交按钮,放在所有题目下方 --> <button type="submit" style="margin: 20px auto; display: block;">Uložiť test</button> </form>
2. 修改stav()函数,生成带序号的表单元素name
调整函数,让每个题目的问题、选项、单选按钮都有唯一的标识,比如otazka_1、spravna_odpoved_1:
<?php function stav($otazkaCislo){ echo " <br><br><br> <table> <tr> <td> <textarea class='otazkaField' name='otazka_$otazkaCislo' cols='30' rows='5'></textarea> </td> </tr> <tr class='trBreak'></tr> <tr> <td>Spravna odpoved: </td> </tr> <tr> <td>A<input type='radio' name='spravna_odpoved_$otazkaCislo' value='A'> <input type='text' name='odpoved_a_$otazkaCislo'></td> </tr> <tr> <td>B<input type='radio' name='spravna_odpoved_$otazkaCislo' value='B'> <input type='text' name='odpoved_b_$otazkaCislo'></td> </tr> <tr> <td>C<input type='radio' name='spravna_odpoved_$otazkaCislo' value='C'> <input type='text' name='odpoved_c_$otazkaCislo'></td> </tr> <tr> <td>D<input type='radio' name='spravna_odpoved_$otazkaCislo' value='D'> <input type='text' name='odpoved_d_$otazkaCislo'></td> </tr> </table> <br><br><br><hr>"; } ?>
3. 编写saveTest.php处理表单提交并存储到数据库
首先建议你创建两个关联的数据库表(以MySQL为例):
-- 存储考试基本信息 CREATE TABLE tests ( id INT AUTO_INCREMENT PRIMARY KEY, nazov VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 存储每个题目,通过test_id关联到对应的考试 CREATE TABLE questions ( id INT AUTO_INCREMENT PRIMARY KEY, test_id INT NOT NULL, otazka TEXT NOT NULL, odpoved_a VARCHAR(255) NOT NULL, odpoved_b VARCHAR(255) NOT NULL, odpoved_c VARCHAR(255) NOT NULL, odpoved_d VARCHAR(255) NOT NULL, spravna_odpoved ENUM('A','B','C','D') NOT NULL, FOREIGN KEY (test_id) REFERENCES tests(id) ON DELETE CASCADE );
然后编写saveTest.php的逻辑,用预处理语句防止SQL注入(新手一定要注意这个!):
<?php // 替换成你的数据库连接信息 $servername = "localhost"; $username = "tvoj_username"; $password = "tvoj_heslo"; $dbname = "tvoj_databaza"; // 创建数据库连接 $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("Pripojenie zlyhalo: " . $conn->connect_error); } // 获取表单提交的数据 $nazovTestu = $_POST['nazovTestu']; $pocetOtazok = $_POST['pocetOtazok']; // 第一步:先插入考试信息到tests表,获取考试ID $sqlTest = "INSERT INTO tests (nazov) VALUES (?)"; $stmtTest = $conn->prepare($sqlTest); $stmtTest->bind_param("s", $nazovTestu); $stmtTest->execute(); $testId = $stmtTest->insert_id; // 获取刚生成的考试ID // 第二步:循环插入每个题目到questions表 for($i = 1; $i <= $pocetOtazok; $i++){ $otazka = $_POST["otazka_$i"]; $odpovedA = $_POST["odpoved_a_$i"]; $odpovedB = $_POST["odpoved_b_$i"]; $odpovedC = $_POST["odpoved_c_$i"]; $odpovedD = $_POST["odpoved_d_$i"]; $spravnaOdpoved = $_POST["spravna_odpoved_$i"]; $sqlQuestion = "INSERT INTO questions (test_id, otazka, odpoved_a, odpoved_b, odpoved_c, odpoved_d, spravna_odpoved) VALUES (?, ?, ?, ?, ?, ?, ?)"; $stmtQuestion = $conn->prepare($sqlQuestion); $stmtQuestion->bind_param("issssss", $testId, $otazka, $odpovedA, $odpovedB, $odpovedC, $odpovedD, $spravnaOdpoved); $stmtQuestion->execute(); $stmtQuestion->close(); } // 关闭连接并跳转回管理员页面 $stmtTest->close(); $conn->close(); header("Location: admin.php?success=1"); exit(); ?>
额外小提示
- 可以给表单加简单的验证,比如检查每个题目是否填写、正确答案是否选中,避免空数据存入数据库;
- 这个方案完全不需要JS,纯PHP+HTML就能实现单按钮提交所有数据,对你来说更友好;
- 预处理语句一定要坚持用,能有效防止SQL注入攻击,是新手必学的安全习惯。
内容的提问来源于stack exchange,提问作者Tchiggy
相关产品推荐
相关产品推荐

