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

基于表单数据数组实现数据库更新的技术问题求助

解决动态表单的问题与选项关联及数据库更新问题

让我们一步步梳理并解决你的问题,先看看现有代码里的几个核心问题:

  1. 循环里重复输出<form>标签,最终页面会生成多个表单,提交时只有最后一个表单的内容会被发送,直接导致前面的问题和选项数据丢失。
  2. 表单字段命名没有建立问题ID与对应选项的关联关系,比如optTitle是单个字段而非关联数组,无法区分每个选项属于哪个问题。
  3. SQL语句直接拼接变量,存在严重的SQL注入风险,必须改用PDO参数绑定。
  4. 隐藏字段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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:04:52