PHP原生学生管理系统:权限分层与CSV导入导出实战
发布时间:2026/9/15 16:10:41 作者:尧图编辑部 阅读量:1,286

简介这是一套基于PHP与MySQL开发的学生成绩管理系统源码面向Web开发初学者及课程设计实践者帮助理解前后端交互、数据库操作与基础权限管理逻辑。资源共33个文件包含6个核心PHP脚本如login.php、database.php、4个CSS样式文件、4个JavaScript交互脚本、14张界面图标PNG及1个SQL建库文件db.sql辅以README.md说明文档和LICENSE协议整体包体积仅2.63MB轻量易部署。已有4363人学习下载体现其在教学实践中的广泛参考价值。读者可直接运行系统体验学生/教师双角色登录默认账号密码明确标注深入分析原生HTML5CSS3前端结构、MySQL8兼容性适配细节以及未封装但具教学意义的数据库连接与CRUD实现逻辑适合用于PHP入门项目拆解与Web全栈开发实训。1. 这不是又一个“PHPMySQL学生管理系统”演示项目而是一份可直接跑通、带完整权限分层与 CSV 导出能力的生产级教学骨架你可能已经见过几十个叫“学生成绩管理系统”的 PHP 项目——它们大多停在登录页就断了数据库字段名和注释对不上教师端压根没实现或者连mysqli_connect()都没加错误处理。但这个StuScoreSystem-main不同它用纯原生 HTML/CSS/JS 实现了学生查分、教师录分、管理员批量导入CSV、按班级/科目/分数段筛选、排序图标联动、二维码分享成绩页甚至保留了dataRoot.php和dataStu.php的双数据访问层设计。它不依赖任何框架却通过database.php封装了连接池式 MySQLi 初始化用root.js和index.js分离了权限逻辑与展示逻辑。适合刚学完 PHP 基础语法、正卡在“怎么把表单提交到数据库”环节的开发者也适合需要快速交付一个轻量级教务后台的中小学校信息员——只要改三处密码、导入一次 SQL、启动本地 PHP 服务就能立刻看到带真实交互的界面而不是对着echo Hello World发呆。2. 从零部署修改 database.php、导入 db.sql、启动服务三步闭环2.1 修改 database.php 中的 MySQL 凭据并理解连接封装逻辑database.php是整个系统数据库访问的唯一入口其核心不是简单地new mysqli()而是做了连接复用与错误兜底。打开该文件定位到第 12 行左右$pw fish;注意此处fish是硬编码密码必须替换为你本地 MySQL 用户通常是root的实际密码。若你使用非 root 用户请同步修改第 10 行的$user root;。再往下看关键逻辑在getDBConnection()函数中function getDBConnection() { static $conn null; if ($conn null) { $conn new mysqli(localhost, root, $pw, stu_score_db, 3306); if ($conn-connect_error) { die(连接失败: . $conn-connect_error . (errno: . $conn-connect_errno . )); } $conn-set_charset(utf8mb4); } return $conn; }static $conn null实现了单例式连接复用避免每次查询都新建连接utf8mb4字符集设置是必须的否则中文姓名或科目名如“数学Ⅱ”可能乱码die()输出带errno的错误码比静默失败更利于排错——比如errno: 1045表示认证失败errno: 1049表示数据库不存在。2.2 执行 db.sql 创建数据库与表结构并验证字符集db.sql文件包含建库、建表、插入默认用户三条语句。用命令行执行推荐mysql -u root -p db.sql输入密码后应无报错输出。随后验证数据库是否创建成功且字符集正确SHOW DATABASES LIKE stu_score_db; USE stu_score_db; SHOW CREATE TABLE students;预期结果中CREATE TABLE语句末尾应含DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci。若显示latin1说明导入时未指定字符集需重新执行mysql -u root -p --default-character-setutf8mb4 db.sql提示MySQL 8.0 默认排序规则为utf8mb4_0900_ai_ci若你的环境是 MySQL 5.7需将db.sql中所有COLLATEutf8mb4_0900_ai_ci替换为COLLATEutf8mb4_unicode_ci否则建表会失败。2.3 启动 PHP 内置服务器并确认路由可达不要依赖老旧的 PHPStudy 或 XAMPP——PHP 7.4 自带php -S命令即可启动开发服务器。进入解压后的项目根目录含login.php的目录执行php -S localhost:8000 -t .此时访问http://localhost:8000/login.php应显示登录页。若报错Failed to open stream: No such file or directory检查当前目录是否正确若页面空白查看终端输出的 PHP 错误如Parse error常见原因是 PHP 版本低于 8.1项目明确要求 PHP ≥ 8.1.3。验证服务是否真正加载了路由在浏览器开发者工具 Network 标签页中刷新登录页观察login.css、login.js是否返回 200 状态码。若 CSS/JS 404说明-t .参数未指向静态资源所在目录——此时需改为php -S localhost:8000 -t ./或明确指定router.php。3. 权限体系解析学生/教师/管理员三级角色如何通过 session 与 URL 路径隔离3.1 登录态校验逻辑分布在 login.php、root.php、index.php 三处系统未使用统一中间件而是通过分散校验实现权限控制。以login.php为例其核心验证代码在第 45 行附近if ($row[role] student) { $_SESSION[user_id] $row[id]; $_SESSION[role] student; header(Location: index.php); exit; } elseif ($row[role] teacher) { $_SESSION[user_id] $row[id]; $_SESSION[role] teacher; header(Location: root.php); exit; } else { $_SESSION[user_id] $row[id]; $_SESSION[role] admin; header(Location: root.php); exit; }学生跳转至index.php仅查看自己成绩教师与管理员均跳转至root.php但后续功能由root.php中的$_SESSION[role]判断分支exit必须存在否则header()重定向后仍会继续执行后续 PHP 代码造成安全漏洞。3.2 root.php 中的权限路由分发与功能开关root.php是教师与管理员的统一入口其顶部有明确的角色判断if ($_SESSION[role] ! teacher $_SESSION[role] ! admin) { header(Location: login.php); exit; }随后根据 GET 参数?action加载不同功能模块action 值对应功能教师可见管理员可见关键限制score_input录入/修改学生成绩✅✅仅能操作所教班级batch_importCSV 批量导入❌✅仅管理员可访问user_manage用户增删改❌✅教师无此链接查看root.php源码你会发现score_input模块中有一段关键 SQL 查询$sql SELECT * FROM students WHERE class_id ? AND subject ?; $stmt $conn-prepare($sql); $stmt-bind_param(is, $_SESSION[class_id], $subject);$_SESSION[class_id]在登录时由dataRoot.php查询并写入 session确保教师只能看到自己任教班级的学生bind_param(is, ...)使用预处理语句防止 SQL 注入这是项目中少有的安全实践亮点。3.3 index.php 的学生侧数据隔离与前端渲染逻辑学生登录后进入index.php其数据获取逻辑在dataStu.php中$sql SELECT s.*, sub.name as subject_name FROM scores s JOIN subjects sub ON s.subject_id sub.id WHERE s.student_id ? ORDER BY s.score DESC; $stmt $conn-prepare($sql); $stmt-bind_param(i, $_SESSION[user_id]);WHERE s.student_id ?严格绑定当前登录学生的 ID杜绝越权查看他人成绩ORDER BY s.score DESC实现默认按分数降序排列配合前端sort_up.png/sort_down.png图标实现点击排序前端 JS 通过fetch(dataStu.php)获取 JSON 数据再用innerHTML渲染表格——虽未用 Vue/React但 DOM 操作逻辑清晰适合初学者模仿。4. CSV 批量导入与导出从 db.sql 结构到 dataRoot.php 的文件解析全流程4.1 db.sql 中的 students 与 scores 表结构决定 CSV 格式db.sql定义了两个核心表CREATE TABLE students ( id int NOT NULL AUTO_INCREMENT, student_id varchar(20) NOT NULL COMMENT 学号, name varchar(50) NOT NULL COMMENT 姓名, class_id int NOT NULL COMMENT 班级ID, PRIMARY KEY (id) ); CREATE TABLE scores ( id int NOT NULL AUTO_INCREMENT, student_id int NOT NULL COMMENT 学生ID, subject_id int NOT NULL COMMENT 科目ID, score decimal(5,2) NOT NULL COMMENT 分数, PRIMARY KEY (id) );因此合法的stuScore.csv必须满足第一行是表头student_id,name,class_id,subject_name,scoresubject_name是科目名称如“数学”程序会在dataRoot.php中通过SELECT id FROM subjects WHERE name ?查找对应subject_idclass_id必须是数据库中已存在的班级 ID否则导入失败4.2 dataRoot.php 中的 CSV 解析函数 parseCSV() 详解dataRoot.php第 120 行起定义了parseCSV()函数其核心步骤如下function parseCSV($file_path) { $handle fopen($file_path, r); $header fgetcsv($handle); // 读取第一行表头 $data []; while (($row fgetcsv($handle)) ! false) { $data[] array_combine($header, $row); } fclose($handle); return $data; }fgetcsv()自动处理逗号分隔与引号包裹如张三,高一(3)班,数学,95.5无需手动explode(,)array_combine($header, $row)将每行数据转为关联数组例如[student_id2114100328, name李四, ...]便于后续字段映射函数返回后调用方batch_import.php会对每条记录执行INSERT INTO scores (...) VALUES (...)并捕获mysqli_error()记录失败行号。4.3 导出 CSV 的实现header() 强制下载与 UTF-8 BOM 处理学生端无导出功能但管理员可在root.php?actionexport触发导出。关键代码在dataRoot.php的exportScores()函数header(Content-Type: text/csv; charsetutf-8); header(Content-Disposition: attachment; filenamescores_export_ . date(Y-m-d) . .csv); echo \xEF\xBB\xBF; // UTF-8 BOM解决 Excel 打开中文乱码 $output fopen(php://output, w); fputcsv($output, [学号, 姓名, 科目, 分数, 录入时间]); foreach ($records as $row) { fputcsv($output, [$row[student_id], $row[name], $row[subject_name], $row[score], $row[created_at]]); } fclose($output);\xEF\xBB\xBF是 UTF-8 BOM 字节序列Windows Excel 依赖它识别 UTF-8 编码fopen(php://output, w)直接将 CSV 写入 HTTP 响应体避免临时文件fputcsv()自动转义逗号、换行符比拼接字符串更安全。5. 排错实战5 类高频问题与对应日志定位方法5.1 “登录失败用户名或密码错误”但凭据确认无误最常见原因是db.sql中的users表未正确插入默认用户。执行以下 SQL 验证SELECT username, password, role, class_id FROM users WHERE username IN (2114100328, teacheroot);预期结果2114100328的password字段值应为sha256(2114100328)的哈希值项目使用 SHA256 加密teacheroot的password应为sha256(fishroot)class_id对teacheroot必须为NULL教师无班级归属否则root.php中的班级过滤会失效。若哈希值不符手动更新UPDATE users SET password SHA2(2114100328, 256) WHERE username 2114100328; UPDATE users SET password SHA2(fishroot, 256) WHERE username teacheroot;5.2 页面显示“Fatal error: Uncaught mysqli_sql_exception”此类错误通常源于 MySQL 8.0 的密码认证插件变更。执行以下命令修复ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY your_password; FLUSH PRIVILEGES;然后重启 MySQL 服务。若使用 Docker需在my.cnf中添加[mysqld] default_authentication_pluginmysql_native_password5.3 CSV 导入后部分学生分数为空检查stuScore.csv是否存在空行或字段数不匹配。用wc -l stuScore.csv查看总行数再用head -n 5 stuScore.csv查看前五行。若发现某行字段数少于表头数如漏写scorefgetcsv()会返回false导致array_combine()报错。解决方案用 Excel 打开 CSV删除空行保存为“CSV UTF-8”格式。5.4 排序图标点击无反应Network 中 dataStu.php 返回 500打开浏览器开发者工具切换到 Console 标签页查看 JS 错误。常见原因是index.js第 87 行的fetch()请求路径错误fetch(dataStu.php?sort sortField order sortOrder)若项目部署在子目录如http://localhost/project/login.php需将路径改为相对路径./dataStu.php或绝对路径/project/dataStu.php。5.5 成绩页面显示 NaN 或空白分数检查scores表中score字段是否为NULL。执行SELECT * FROM scores WHERE score IS NULL LIMIT 5;若存在说明录入时未校验必填项。修复方法在root.php?actionscore_input的表单提交逻辑中增加 PHP 层校验if (empty($_POST[score]) || !is_numeric($_POST[score])) { $_SESSION[error] 分数必须为数字; header(Location: root.php?actionscore_input); exit; }提示所有用户输入必须同时做前端 JS 校验index.js中已有和后端 PHP 校验二者缺一不可。6. 进阶技巧用 PHP 内置函数实现成绩统计图表与 PDF 导出6.1 用 imagecreate() 生成柱状图成绩单无需 GD 库扩展项目未自带图表功能但可利用 PHP 原生 GD 函数快速生成 PNG 成绩图。在index.php底部添加?php // 生成学生成绩柱状图 $width 400; $height 200; $im imagecreate($width, $height); $bg imagecolorallocate($im, 255, 255, 255); $bar_color imagecolorallocate($im, 70, 130, 180); $border_color imagecolorallocate($im, 0, 0, 0); // 假设 $scores 是从 dataStu.php 获取的成绩数组 $max_score max(array_column($scores, score)); $scale ($height - 40) / $max_score; foreach ($scores as $i $s) { $x 50 $i * 80; $y $height - 20 - ($s[score] * $scale); imagefilledrectangle($im, $x, $y, $x 50, $height - 20, $bar_color); imagerectangle($im, $x, $y, $x 50, $height - 20, $border_color); imagestring($im, 2, $x 10, $height - 15, $s[subject_name], $border_color); } header(Content-Type: image/png); imagepng($im); imagedestroy($im); exit; ?将此代码保存为chart.php在index.php中img srcchart.php即可显示动态图表。注意需确保 PHP 编译时启用了 GD 支持php -m | grep gd。6.2 用 TCPDF 库实现 PDF 成绩单导出兼容 PHP 8.1下载 TCPDFhttps://github.com/tecnickcom/tcpdf解压后将tcpdf.php和config/目录放入项目lib/文件夹。在root.php中添加导出按钮点击后调用require_once(lib/tcpdf/tcpdf.php); $pdf new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, UTF-8, false); $pdf-AddPage(); $pdf-writeHTML(h2学生成绩单/h2table border1trth科目/thth分数/th/tr, true, false, true, false, ); foreach ($scores as $s) { $pdf-writeHTML(trtd . $s[subject_name] . /tdtd . $s[score] . /td/tr, true, false, true, false, ); } $pdf-Output(score_report.pdf, D);true, false, true, false, 参数控制 HTML 解析、自动分页、表格边框等行为Output(filename.pdf, D)中D表示强制下载I表示内联显示。6.3 优化 MySQL 查询性能为高频字段添加复合索引当前scores表仅对id有主键索引但教师按班级查分、学生按科目查分均为高频操作。执行以下 SQL 提升响应速度-- 为教师按班级科目查分优化 CREATE INDEX idx_class_subject ON scores(class_id, subject_id); -- 为学生按科目查分优化 CREATE INDEX idx_student_subject ON scores(student_id, subject_id); -- 查看索引效果 EXPLAIN SELECT * FROM scores WHERE student_id 123 AND subject_id 5;EXPLAIN输出中type应为refkey应显示刚创建的索引名rows应远小于全表行数。本文还有配套的精品资源点击获取