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

PHP学生选课系统提交动态复选框值时如何与数据库比对防重复

学生选课系统重复选课校验逻辑修复方案

现有代码核心问题

  • 逐课程边校验边插入:校验到重复课程前,无重复的课程已经被写入数据库,无法拦截整次提交
  • 跳转后未终止执行:调用header()跳转后没有追加exit/die语句,后续代码仍会继续执行
  • 单课程重复查询性能损耗:每次遍历都单独查询已选课程和课程基础信息,选课数量大时数据库压力高
  • 单课程插入即跳转:第一门课插入成功就直接跳转,剩余选中的课程不会被写入

修复后提交处理代码

<?php
// 表单提交处理逻辑
if (isset($_POST['submit'])) {
    // 校验是否选中课程
    if (!isset($_POST['inChk']) || empty($_POST['inChk'])) {
        header('location: cos_reg.php?data=empty');
        exit;
    }
    $selectedCourses = $_POST['inChk'];
    $userRegNo = $_SESSION['regno'];
    
    // 1. 一次性查询当前用户所有已选课程存入数组
    $existCourses = [];
    $checkSql = "SELECT CourseCode FROM cregtbl WHERE RegNo = ?";
    if ($stmt = $con->prepare($checkSql)) {
        $stmt->bind_param("s", $userRegNo);
        $stmt->execute();
        $result = $stmt->get_result();
        while ($row = $result->fetch_assoc()) {
            $existCourses[] = $row['CourseCode'];
        }
        $stmt->close();
    }
    
    // 2. 全量校验所有选中课程是否重复
    $duplicateList = [];
    foreach ($selectedCourses as $courseCode) {
        if (in_array($courseCode, $existCourses)) {
            $duplicateList[] = $courseCode;
        }
    }
    // 存在重复直接拦截整次提交,跳转提示
    if (!empty($duplicateList)) {
        // 如需展示具体重复课程,可将$duplicateList拼接至URL参数
        header('location: cos_reg.php?msg=duplicate');
        exit;
    }
    
    // 3. 批量查询所有选中课程的基础信息
    $courseBaseInfo = [];
    $placeholder = rtrim(str_repeat('?,', count($selectedCourses)), ',');
    $paramType = str_repeat('s', count($selectedCourses));
    $courseSql = "SELECT CourseCode, CourseTitle, CreditUnit, Status FROM admintbl WHERE CourseCode IN ($placeholder)";
    if ($stmt = $con->prepare($courseSql)) {
        $stmt->bind_param($paramType, ...$selectedCourses);
        $stmt->execute();
        $result = $stmt->get_result();
        while ($row = $result->fetch_assoc()) {
            $courseBaseInfo[$row['CourseCode']] = $row;
        }
        $stmt->close();
    }
    
    // 4. 所有校验通过后统一插入选课数据
    $insertStatus = true;
    $insertSql = "INSERT INTO cregtbl(StudentName, Email, RegNo, Level, Department, Semester, Reg_Date, CourseCode, CourseTitle, CreditUnit, Status) VALUES (?,?,?,?,?,?,?,?,?,?,?)";
    $stmt = $con->prepare($insertSql);
    foreach ($selectedCourses as $code) {
        // 过滤非法课程编码
        if (!isset($courseBaseInfo[$code])) continue;
        $info = $courseBaseInfo[$code];
        $stmt->bind_param(
            "sssssssssss",
            $_SESSION['name'],
            $_SESSION['email'],
            $userRegNo,
            $_SESSION['level'],
            $_SESSION['dept'],
            $_SESSION['semester'],
            $rdate,
            $info['CourseCode'],
            $info['CourseTitle'],
            $info['CreditUnit'],
            $info['Status']
        );
        if (!$stmt->execute()) {
            $insertStatus = false;
            break;
        }
    }
    $stmt->close();
    
    // 最终结果跳转
    if ($insertStatus) {
        header('location: cos_reg.php?msg3=registered');
    } else {
        header('location: cos_reg.php?msg=insert_fail&err=' . urlencode($con->error));
    }
    exit;
}
?>

逻辑优化说明

  • 全量前置校验:所有选课校验通过后才执行写入,只要存在重复就直接拦截整次提交,不会出现部分写入的问题
  • 降低数据库压力:将逐次查询改为批量查询,数据库交互次数从2*N次降低为3次,性能提升明显
  • 强制终止执行:所有header跳转后追加exit语句,避免后续代码意外执行
  • 兼容原有逻辑:保留原有的跳转参数标识,无需修改前端提示相关代码

内容的提问来源于stack exchange,提问作者Ndongesit Edet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:54:01