如何实现仅展示分配给当前用户的考试数据?
问题分析与解决方案
当前代码的核心问题是SQL查询未过滤当前登录用户的已分配考试,直接从exams表取出所有考试数据,导致所有用户都能看到全部考试。要实现“仅展示分配给当前用户的考试”,需要结合用户分配关系表和当前登录用户的ID来过滤数据。
前提假设
假设存在一个用于记录考试与用户分配关系的表(例如exam_assignments),表结构至少包含:
exam_id:关联的考试IDuser_id:被分配该考试的用户ID
解决方案步骤
1. 修改SQL查询语句
将原查询改为关联用户分配表,仅获取当前登录用户被分配的考试:
session_start(); // 确保当前用户已登录,获取用户ID(需根据实际session存储字段调整) $current_user_id = $_SESSION['user_id'] ?? null; $title = "ExamList"; // 使用JOIN关联分配表,过滤当前用户的考试 $query = "SELECT e.id, e.title, e.no_questions, e.points, e.schedule, e.time_limit, e.link FROM exams e JOIN exam_assignments ea ON e.id = ea.exam_id WHERE ea.user_id = $current_user_id"; $exams = get_data($query);
2. 修复SQL注入风险(关键优化)
原get_data函数直接执行传入的查询语句,存在严重的SQL注入风险。建议改用预处理语句:
function get_data($query, $params = []){ $conn = db_connect(); $stmt = $conn->prepare($query); // 绑定参数(如果有) if(!empty($params)){ $types = str_repeat('i', count($params)); // 假设参数都是整数类型,根据实际调整 $stmt->bind_param($types, ...$params); } $stmt->execute(); $result = $stmt->get_result(); $output = []; while($row = $result->fetch_assoc()){ $output[$row['id']] = $row; } $stmt->close(); $conn->close(); return $output; } // 调用时传入参数 $current_user_id = $_SESSION['user_id'] ?? null; $query = "SELECT e.id, e.title, e.no_questions, e.points, e.schedule, e.time_limit, e.link FROM exams e JOIN exam_assignments ea ON e.id = ea.exam_id WHERE ea.user_id = ?"; $exams = get_data($query, [$current_user_id]);
3. 增加登录状态校验
在获取考试数据前,先校验用户是否已登录,避免未登录用户访问:
session_start(); if(!isset($_SESSION['user_id'])){ // 未登录,跳转到登录页或提示权限不足 header("Location: login.php"); exit; }
最终修改后的完整代码片段
<?php function get_data($query, $params = []){ $conn = db_connect(); $stmt = $conn->prepare($query); if(!empty($params)){ $types = str_repeat('i', count($params)); $stmt->bind_param($types, ...$params); } $stmt->execute(); $result = $stmt->get_result(); $output = []; while($row = $result->fetch_assoc()){ $output[$row['id']] = $row; } $stmt->close(); $conn->close(); return $output; } session_start(); // 校验登录状态 if(!isset($_SESSION['user_id'])){ header("Location: login.php"); exit; } $title = "ExamList"; $current_user_id = $_SESSION['user_id']; // 关联分配表查询当前用户的考试 $query = "SELECT e.id, e.title, e.no_questions, e.points, e.schedule, e.time_limit, e.link FROM exams e JOIN exam_assignments ea ON e.id = ea.exam_id WHERE ea.user_id = ?"; $exams = get_data($query, [$current_user_id]); ?> <?php foreach($exams as $exam){?> <div class="col-xl-3 col-md-6 mb-4"> <div class="card border-round pink-gradient exam_card"> <div class="card-body text-center"> <h4><?php echo $exam['title']; ?></h4> <div class="btn-group dropright float-right"> <button type="button" class="btn dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <i class="fa fa-ellipsis-v" aria-hidden="true"></i> </button> <div class="dropdown-menu border-round pink-gradient dropdown_body"> <a href="examinees_result.php?id=<?php echo $exam['id']; ?>" class="card_link">View</a> <hr> <button id="copy" class="copy_link" data="<?php echo "http://" . $_SERVER['SERVER_NAME'].$proj_name."/exam.php?link=".$exam['link'];?>">Copy Link</button> <hr> </div> </div> </div> </div> </div> <?php } ?>
说明
- 如果你的用户-考试分配逻辑不是用关联表实现的(例如
exams表直接有assigned_user_id字段),只需调整SQL查询的过滤条件即可,核心思路是基于当前登录用户ID筛选数据。 - 预处理语句的使用能有效防止SQL注入,提升系统安全性,这是生产环境必须做的优化。
内容的提问来源于stack exchange,提问作者John Marvin
相关产品推荐
相关产品推荐

