基于表单数据数组实现数据库更新的技术问题求助
解决动态表单的问题与选项关联及数据库更新问题
让我们一步步梳理并解决你的问题,先看看现有代码里的几个核心问题:
- 循环里重复输出
<form>标签,最终页面会生成多个表单,提交时只有最后一个表单的内容会被发送,直接导致前面的问题和选项数据丢失。 - 表单字段命名没有建立问题ID与对应选项的关联关系,比如
optTitle是单个字段而非关联数组,无法区分每个选项属于哪个问题。 - SQL语句直接拼接变量,存在严重的SQL注入风险,必须改用PDO参数绑定。
- 隐藏字段
qid和questid的输出逻辑错误,无法正确传递每个问题和选项的唯一ID。
第一步:修正表单生成代码(myform.php)
把表单标签移到循环外面,同时调整字段命名,让每个问题和选项通过问题ID(qid)关联起来:
<?php $cid = $_GET['course_id']; $host = 'localhost'; $dbname = 'einstower_elearn'; $username = "root"; $password = ""; try { $pdo = new PDO("mysql:dbname=$dbname;host=$host", $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { die("数据库连接失败: " . $e->getMessage()); } // 获取当前课程下的所有问题 $stmtQuestions = $pdo->prepare("SELECT * FROM questions WHERE eid = :cid"); $stmtQuestions->bindParam(':cid', $cid, PDO::PARAM_INT); $stmtQuestions->execute(); $questions = $stmtQuestions->fetchAll(PDO::FETCH_ASSOC); ?> <!-- 把<form>标签放在循环外面,只生成一个表单 --> <form method="POST" action="edit_exam_course.php" enctype="multipart/form-data"> <?php if (!empty($questions)): ?> <?php foreach ($questions as $question): $qid = $question['qid']; $questionText = $question['qns']; ?> <div class="row form-group" style="padding-top:40px !important;"> <div class="col-sm-2"> <label class="control-label modal-label">Question</label> </div> <div class="col-sm-10"> <!-- 用问题ID作为数组键,关联问题内容 --> <input type="text" value="<?= htmlspecialchars($questionText) ?>" class="form-control" name="questions[<?= $qid ?>]" required> </div> </div> <?php // 获取当前问题的所有选项 $stmtOptions = $pdo->prepare("SELECT * FROM options WHERE qid = :qid"); $stmtOptions->bindParam(':qid', $qid, PDO::PARAM_INT); $stmtOptions->execute(); $options = $stmtOptions->fetchAll(PDO::FETCH_ASSOC); ?> <?php foreach ($options as $option): $optionId = $option['optionid']; $optionText = $option['option']; ?> <div class="row form-group"> <!-- 修正之前的拼写错误rwo为row --> <div class="col-md-12"> <!-- 用问题ID和选项ID关联,确保每个选项对应正确的问题 --> <input type="hidden" name="options[<?= $qid ?>][ids][]" value="<?= $optionId ?>"> <input name="options[<?= $qid ?>][texts][]" value="<?= htmlspecialchars($optionText) ?>" class="form-control input-md" type="text"> </div> </div> <?php endforeach; ?> <?php endforeach; ?> <?php else: ?> <p>当前课程暂无问题</p> <?php endif; ?> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove"></span> Cancel</button> <button type="submit" name="update_exam_course" class="btn btn-primary"><span class="glyphicon glyphicon-check"></span>Update</button> </div> </form>
关键改动说明:
- 将
<form>移到循环外,确保所有问题和选项都在同一个表单里提交,避免数据丢失。 - 字段命名采用嵌套数组:
questions[$qid]存储每个问题的修改后内容,options[$qid][ids][]和options[$qid][texts][]分别存储对应问题的选项ID和修改后的文本,完美建立问题与选项的关联。 - 使用
htmlspecialchars()转义输出内容,防止XSS攻击。 - 所有SQL查询改用PDO参数绑定,彻底避免SQL注入风险。
第二步:处理表单提交并更新数据库(edit_exam_course.php)
现在可以正确接收每个问题及其对应的选项数据,通过唯一ID更新数据库:
<?php session_start(); include_once('connection.php'); if(isset($_POST['update_exam_course'])){ // 确保connection.php中使用的是PDO连接 global $pdo; try { // 开启事务,确保更新操作的原子性 $pdo->beginTransaction(); // 更新问题内容 if (!empty($_POST['questions'])) { foreach ($_POST['questions'] as $qid => $newQuestionText) { $stmt = $pdo->prepare("UPDATE questions SET qns = :qns WHERE qid = :qid"); $stmt->bindParam(':qns', $newQuestionText, PDO::PARAM_STR); $stmt->bindParam(':qid', $qid, PDO::PARAM_INT); $stmt->execute(); } } // 更新选项内容 if (!empty($_POST['options'])) { foreach ($_POST['options'] as $qid => $optionData) { $optionIds = $optionData['ids']; $optionTexts = $optionData['texts']; // 遍历每个选项,通过optionid更新 foreach ($optionIds as $index => $optionId) { $newOptionText = $optionTexts[$index]; $stmt = $pdo->prepare("UPDATE options SET option = :option WHERE optionid = :optionid"); $stmt->bindParam(':option', $newOptionText, PDO::PARAM_STR); $stmt->bindParam(':optionid', $optionId, PDO::PARAM_INT); $stmt->execute(); } } } // 提交事务 $pdo->commit(); echo "更新成功!"; // 可根据需求跳转回原页面 // header("Location: myform.php?course_id=" . $_GET['course_id']); // exit; } catch(PDOException $e) { // 回滚事务,避免部分更新导致的数据不一致 $pdo->rollBack(); die("更新失败: " . $e->getMessage()); } } ?>
关键逻辑说明:
- 使用数据库事务,确保所有更新要么全部成功,要么全部回滚,避免数据不一致。
- 遍历
$_POST['questions']数组,通过qid更新对应的问题内容。 - 遍历
$_POST['options']数组,每个问题ID下对应一组选项ID和文本,通过optionid精准更新每个选项的内容。
内容的提问来源于stack exchange,提问作者Alexander Omoruyi
相关产品推荐
相关产品推荐

