ThinkPHP 6.x 学生宿舍管理系统毕设实战指南
2026/9/16 3:54:56 网站建设 项目流程

简介:这是一套基于ThinkPHP框架开发的学生宿舍公寓管理系统毕业设计源码,面向计算机类专业在校生、教师及初级开发者,适用于毕业设计、课程设计、项目实训与入门级Web开发实践。资源共367个文件,以180个PHP后端逻辑文件为核心,辅以98个JavaScript交互脚本、19个CSS样式文件及14个HTML页面模板,完整覆盖用户管理、房间分配、报修处理、费用统计等核心业务模块;前端采用Bootstrap、Font Awesome及自定义主题样式,兼顾响应式布局与基础UI规范。压缩包仅2.22MB,轻量易部署,所有功能均经实测运行通过。目前已有121人学习下载,配套README说明清晰,代码结构分层合理,注释充分,既可开箱即用,也便于二次开发拓展功能或适配其他校园管理场景。

1. 这不是套模板:用 ThinkPHP 搭建真实可运行的学生宿舍公寓管理系统,专为毕业设计场景优化

很多同学拿到“基于ThinkPHP学生宿舍公寓管理系统”这个毕设题目时,第一反应是去 GitHub 或某站搜一个 ZIP 包解压就交——结果部署报错、数据库连不上、权限控制形同虚设,答辩被问一句“你改过哪行核心代码?”当场卡壳。实际上,这个标题背后是一套典型的中小型业务系统落地路径:它不追求高并发或微服务,但必须体现分层结构意识、数据一致性保障、角色权限闭环、以及符合高校宿舍管理逻辑的真实字段设计。它适合计算机/软件工程专业本科毕设,尤其适配 PHP 开发能力中等、数据库设计已掌握 ER 图、但缺乏完整项目交付经验的同学。关键不在“用 ThinkPHP”,而在于如何让 ThinkPHP 成为你理解 MVC 分离、关联模型、表单验证、RBAC 权限控制的脚手架,而不是遮掩技术短板的包装纸。本文全程基于 ThinkPHP 官方稳定分支(以 ThinkPHP 6.1 为主,兼容 PHP 7.4–8.2),所有命令、配置、SQL 和控制器逻辑均可在本地 WAMP/MAMP/XAMPP 环境中 5 分钟内复现,不依赖任何第三方魔改框架或“免配置一键包”。

2. 为什么选 ThinkPHP 6.x 而非 3.2 或 5.x:版本选型与环境准备的硬约束

2.1 ThinkPHP 6.x 是当前毕业设计最稳妥的选择

网络热词中频繁出现“thinkphp 3.2 版本兼容 php8”,这恰恰说明旧版已成雷区。ThinkPHP 3.2 基于 PHP 5.3+ 设计,强制要求mysql扩展(PHP 7.0+ 已废弃),且无命名空间、无 Composer 自动加载机制,在 PHP 8.0+ 环境下会直接触发Fatal error: Uncaught Error: Call to undefined function mysql_connect()。而 ThinkPHP 6.x(当前主流为 6.1.x)采用 PSR-4 自动加载、原生支持 PDO、内置多应用模式、路由分组清晰,更重要的是——其官方文档完整、社区问答活跃、错误提示明确,对调试友好度远超旧版。毕业设计不是生产环境压测,稳定性、可读性、可解释性才是核心指标。

2.2 本地开发环境最小化搭建(Windows/macOS/Linux 通用)

提示:不要用 XAMPP 内置的旧版 PHP。务必单独安装 PHP 8.0+(推荐 8.1),并启用pdo_mysql,mbstring,curl,json,xml扩展。可通过php -m | grep pdo验证。

使用 Composer 创建项目(命令需在终端中执行):

# 全局安装 Composer(若未安装) curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer # Linux/macOS # Windows 用户下载 composer-setup.exe 并运行 # 创建 ThinkPHP 6.1 项目(指定稳定版本,避免 dev 分支不稳定) composer create-project topthink/think=6.1.0 student-dorm-system --ignore-platform-reqs # 进入项目目录并启动内置服务器(端口 8000) cd student-dorm-system php think run

执行后访问http://127.0.0.1:8000,应看到 ThinkPHP 默认欢迎页。若提示The requested URL was not found on this server,检查public/.htaccess是否存在(Apache)或 Nginx 配置是否指向public/目录;若提示Class 'think\App' not found,说明 Composer 未正确加载 autoload,执行composer dump-autoload

2.3 数据库初始化:从 ER 图到真实 SQL 的三步转化

毕业设计中“数据库er图用哪种方法”高频出现,本质是混淆了设计工具与落地执行。我们跳过 PowerDesigner 等重型工具,用最简方式生成可执行 SQL:

  1. 核心实体识别(紧扣“学生宿舍公寓管理”业务):

    • student(学号、姓名、院系、班级、联系电话)
    • dormitory(楼号、房间号、床位数、当前入住数、状态【空闲/满员/维修】)
    • dorm_assignment(分配记录:学生ID、宿舍ID、入住日期、退宿日期、是否续住)
    • admin_user(管理员:账号、密码哈希、角色【超级管理员/楼长/辅导员】)
    • repair_record(报修记录:宿舍ID、报修人、问题描述、处理状态、处理人、完成时间)
  2. 关系确认(避免常见错误):

    • 一个学生只能住一个床位 →dorm_assignment.student_id是外键,且UNIQUE
    • 一个宿舍可多人入住 →dorm_assignment.dormitory_id允许重复
    • 报修由学生发起,但由楼长处理 →repair_record.student_idrepair_record.handler_id分属不同角色
  3. 生成可执行 SQL(MySQL 5.7+)

-- 创建数据库(字符集必须为 utf8mb4,避免微信昵称等 emoji 存储失败) CREATE DATABASE IF NOT EXISTS dorm_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE dorm_db; -- 学生表 CREATE TABLE `student` ( `id` int UNSIGNED NOT NULL AUTO_INCREMENT, `student_id` char(12) NOT NULL COMMENT '学号,如20220001001', `name` varchar(20) NOT NULL, `department` varchar(50) DEFAULT NULL, `class` varchar(30) DEFAULT NULL, `phone` char(11) DEFAULT NULL, `created_at` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_student_id` (`student_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 宿舍表 CREATE TABLE `dormitory` ( `id` int UNSIGNED NOT NULL AUTO_INCREMENT, `building_no` varchar(10) NOT NULL COMMENT '楼号,如A栋、3号楼', `room_no` varchar(10) NOT NULL COMMENT '房间号,如301、B205', `bed_count` tinyint UNSIGNED NOT NULL DEFAULT 4, `occupied_count` tinyint UNSIGNED NOT NULL DEFAULT 0, `status` enum('vacant','full','under_maintenance') NOT NULL DEFAULT 'vacant', `created_at` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_building_room` (`building_no`,`room_no`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 分配表(核心业务表) CREATE TABLE `dorm_assignment` ( `id` int UNSIGNED NOT NULL AUTO_INCREMENT, `student_id` int UNSIGNED NOT NULL, `dormitory_id` int UNSIGNED NOT NULL, `check_in_date` date NOT NULL, `check_out_date` date DEFAULT NULL COMMENT '为空表示尚未退宿', `is_renewed` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否续住', `created_at` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_student_id` (`student_id`), -- 保证一人一寝 KEY `idx_dormitory_id` (`dormitory_id`), CONSTRAINT `fk_assignment_student` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`) ON DELETE CASCADE, CONSTRAINT `fk_assignment_dormitory` FOREIGN KEY (`dormitory_id`) REFERENCES `dormitory` (`id`) ON DELETE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

注意:ON DELETE CASCADE用于学生删除时自动清理其分配记录;而宿舍删除设为RESTRICT,防止误删导致数据孤儿。这是毕业设计中体现“数据完整性意识”的关键细节。

3. 核心功能模块实现:从控制器到视图的完整链路

3.1 宿舍分配模块:解决“一人一寝”与“床位动态统计”的双重约束

分配逻辑不能仅靠前端下拉框选择,必须在服务层校验。ThinkPHP 6 的验证器(Validate)和模型事件(Model Event)是最佳组合。

首先定义app/validate/DormAssignment.php验证器:

<?php declare (strict_types = 1); namespace app\validate; use think\Validate; class DormAssignment extends Validate { protected $rule = [ 'student_id' => 'require|number|exists:student,id', 'dormitory_id' => 'require|number|exists:dormitory,id', 'check_in_date' => 'require|date|after:yesterday', ]; protected $message = [ 'student_id.require' => '请选择学生', 'student_id.exists' => '该学生不存在', 'dormitory_id.exists' => '该宿舍不存在', 'check_in_date.after' => '入住日期不能早于今天', ]; // 自定义场景:分配时需检查宿舍是否满员 protected $scene = [ 'assign' => ['student_id', 'dormitory_id', 'check_in_date'], ]; }

然后在app/controller/Admin/DormAssignmentController.php中实现分配逻辑:

<?php declare (strict_types = 1); namespace app\controller\Admin; use app\BaseController; use app\model\DormAssignment as AssignmentModel; use app\model\Dormitory; use app\model\Student; use app\validate\DormAssignment as AssignmentValidate; class DormAssignmentController extends BaseController { public function assign() { if ($this->request->isPost()) { $data = $this->request->post(); // 使用验证器场景 $validate = new AssignmentValidate(); if (!$validate->scene('assign')->check($data)) { return json(['code' => 0, 'msg' => $validate->getError()]); } // 关键:事务内检查并更新床位数 $result = \think\facade\Db::transaction(function () use ($data) { // 1. 查询目标宿舍当前占用数 $dorm = Dormitory::find($data['dormitory_id']); if (!$dorm || $dorm->status !== 'vacant') { throw new \Exception('该宿舍不可分配'); } if ($dorm->occupied_count >= $dorm->bed_count) { throw new \Exception('该宿舍床位已满'); } // 2. 创建分配记录 $assignment = new AssignmentModel(); $assignment->student_id = $data['student_id']; $assignment->dormitory_id = $data['dormitory_id']; $assignment->check_in_date = $data['check_in_date']; $assignment->save(); // 3. 更新宿舍占用数(原子操作) $dorm->occupied_count += 1; $dorm->status = $dorm->occupied_count >= $dorm->bed_count ? 'full' : 'vacant'; $dorm->save(); return $assignment->id; }); if ($result) { return json(['code' => 1, 'msg' => '分配成功']); } else { return json(['code' => 0, 'msg' => '分配失败,请重试']); } } // GET 请求:渲染分配页面,预加载学生和宿舍列表 $students = Student::field('id,student_id,name,department,class')->select(); $dormitories = Dormitory::where('status', 'vacant')->select(); return view('assign', compact('students', 'dormitories')); } }

逻辑说明:Db::transaction确保“创建分配记录”与“更新宿舍占用数”要么全部成功,要么全部回滚。若不加事务,极端情况下可能出现分配成功但床位数未更新,导致超员。参数说明:$data['student_id']来自前端表单,经验证器确保其真实存在;$dorm->status !== 'vacant'排除维修中宿舍;$dorm->occupied_count >= $dorm->bed_count是业务硬约束,比单纯查COUNT(*)更高效。

3.2 权限控制模块:用 RBAC 实现“楼长只能管自己楼”的真实隔离

毕业设计常忽略权限粒度,“管理员”一刀切。ThinkPHP 6 原生不带 RBAC,但通过中间件 + 数据库查询可轻量实现。

创建权限中间件app/middleware/RoleCheck.php

<?php declare (strict_types = 1); namespace app\middleware; use app\model\AdminUser; use think\Request; use think\Response; class RoleCheck { public function handle(Request $request, \Closure $next) { $adminId = session('admin_id'); if (!$adminId) { return redirect('/admin/login'); } $admin = AdminUser::find($adminId); if (!$admin) { session(null); // 清除无效 session return redirect('/admin/login'); } // 超级管理员跳过检查 if ($admin->role === 'super_admin') { return $next($request); } // 楼长:只能访问自己负责的楼号(假设 admin_user 表有 building_managed 字段) if ($admin->role === 'building_manager' && $admin->building_managed) { $currentRoute = $request->path(); // 规则:/admin/dormitory/list?building=A栋 → 允许;/admin/student/list → 拒绝 if (strpos($currentRoute, '/admin/dormitory/') === 0) { $buildingParam = $request->param('building', ''); if ($buildingParam && $buildingParam !== $admin->building_managed) { return Response::create('无权访问该楼栋数据', 'html', 403); } } } return $next($request); } }

app/middleware.php中注册:

return [ // 全局中间件 \app\middleware\RoleCheck::class, ];

参数说明:$admin->building_managed存储楼长负责的楼号(如“A栋”),通过 URL 参数?building=A栋传递,中间件实时校验。这种方式无需复杂权限表,却能精准控制数据可见性,是毕业设计中“够用且可讲清”的典型方案。

4. 关联删除与数据一致性:ThinkPHP 中避免“删宿舍学生还在住”的陷阱

4.1 外键约束 vs 模型事件:两种方案的适用边界

网络热词中“thinkphp 关联删除”常被误解为“一条命令删全表”。实际需区分场景:

  • 物理删除(DELETE):必须依赖数据库外键ON DELETE CASCADE,如前文dorm_assignment.student_id的约束。这是最可靠的数据一致性保障,DB 层强制执行。
  • 逻辑删除(UPDATE status=0):ThinkPHP 模型提供deleteTime软删除,适用于学生退学但需保留历史记录的场景。

但宿舍表(dormitory)的删除策略不同:宿舍物理删除时,必须阻止已分配学生的宿舍被删(即ON DELETE RESTRICT),而非级联删除分配记录——因为分配记录本身是业务事实,删除宿舍不等于抹去历史入住行为。

4.2 在控制器中实现安全删除宿舍的完整流程

app/controller/Admin/DormitoryController.php中的destroy方法:

public function destroy($id) { $dorm = Dormitory::find($id); if (!$dorm) { return json(['code' => 0, 'msg' => '宿舍不存在']); } // 检查是否有学生正在入住(非退宿状态) $activeAssignments = AssignmentModel::where('dormitory_id', $id) ->whereNull('check_out_date') // check_out_date 为空 = 尚未退宿 ->count(); if ($activeAssignments > 0) { return json(['code' => 0, 'msg' => "无法删除:该宿舍有 {$activeAssignments} 名学生正在入住"]); } // 检查是否有未处理报修 $pendingRepairs = RepairRecord::where('dormitory_id', $id) ->where('status', 'pending') ->count(); if ($pendingRepairs > 0) { return json(['code' => 0, 'msg' => "无法删除:该宿舍有 {$pendingRepairs} 条待处理报修"]); } // 执行删除(此时可安全删除) if ($dorm->delete()) { return json(['code' => 1, 'msg' => '宿舍删除成功']); } else { return json(['code' => 0, 'msg' => '删除失败']); } }

关键点:whereNull('check_out_date')是判断“当前入住”的核心条件,比WHERE status='living'更符合业务语义(状态字段易被篡改,NULL 值不可伪造)。此逻辑在控制器中显式编写,比依赖模型钩子更直观,便于答辩时讲解“为什么这里要查两次”。

4.3 修复已存在的数据不一致:用 SQL 快速清理脏数据

若前期开发中已产生“宿舍被删但分配记录残留”的脏数据,可用以下 SQL 修复:

-- 查找所有 dormitory_id 不存在于 dormitory 表的分配记录 SELECT * FROM dorm_assignment WHERE dormitory_id NOT IN (SELECT id FROM dormitory); -- 安全删除(先备份!) DELETE FROM dorm_assignment WHERE dormitory_id NOT IN (SELECT id FROM dormitory); -- 同步更新宿舍表 occupied_count(修复因程序异常导致的计数偏差) UPDATE dormitory d JOIN ( SELECT dormitory_id, COUNT(*) as cnt FROM dorm_assignment WHERE check_out_date IS NULL GROUP BY dormitory_id ) a ON d.id = a.dormitory_id SET d.occupied_count = a.cnt;

提示:执行前务必备份数据库。COUNT(*)子查询比循环查每条记录效率高两个数量级,适合毕业设计中快速收尾。

5. 毕业设计答辩必答技巧:三个让老师眼前一亮的技术细节

5.1 在登录页展示“当前系统负载”:用 ThinkPHP 命令行快速实现

答辩时老师常问“你怎么知道系统性能?”——与其空谈“用了Redis缓存”,不如展示一个真实指标。ThinkPHP 内置think命令可获取内存与请求信息:

app/view/admin/login.html底部添加:

<div class="footer-info"> <small> 系统状态:<?php $mem = memory_get_usage() / 1024 / 1024; $reqTime = round(microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'], 3); echo "内存使用 {$mem:.2f}MB | 请求耗时 {$reqTime}s"; ?> </small> </div>

逻辑说明:memory_get_usage()返回当前脚本内存占用,$_SERVER['REQUEST_TIME_FLOAT']是请求开始时间戳,二者相减得真实响应时间。无需额外扩展,5 行代码即可体现“性能可观测性”,且完全符合毕业设计深度。

5.2 导出宿舍分配表时自动标注“续住学生”:用 ExcelWriter 实现差异化样式

学生续住是宿舍管理关键指标,但普通导出难以突出。使用phpoffice/phpspreadsheet(Composer 安装):

composer require phpoffice/phpspreadsheet

app/controller/Admin/ExportController.php中:

use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\Style\Font; public function exportAssignments() { $assignments = AssignmentModel::with(['student', 'dormitory']) ->whereNotNull('check_out_date') ->select(); $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setCellValue('A1', '学号')->setCellValue('B1', '姓名')->setCellValue('C1', '宿舍')->setCellValue('D1', '入住日期')->setCellValue('E1', '退宿日期')->setCellValue('F1', '是否续住'); $row = 2; foreach ($assignments as $item) { $sheet->setCellValue("A{$row}", $item->student->student_id); $sheet->setCellValue("B{$row}", $item->student->name); $sheet->setCellValue("C{$row}", "{$item->dormitory->building_no}{$item->dormitory->room_no}"); $sheet->setCellValue("D{$row}", $item->check_in_date); $sheet->setCellValue("E{$row}", $item->check_out_date); $sheet->setCellValue("F{$row}", $item->is_renewed ? '是' : '否'); // 续住学生整行标红 if ($item->is_renewed) { $styleArray = [ 'font' => ['color' => ['rgb' => 'FF0000']], ]; $sheet->getStyle("A{$row}:F{$row}")->applyFromArray($styleArray); } $row++; } $writer = new Xlsx($spreadsheet); $filename = '宿舍分配导出_' . date('YmdHis') . '.xlsx'; header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="' . $filename . '"'); header('Cache-Control: max-age=0'); $writer->save('php://output'); }

效果:导出 Excel 中续住学生行文字变红,无需老师手动筛选。这展示了“业务需求驱动技术选型”的思维,比单纯说“用了PHPExcel”更有说服力。

5.3 用 Git 提交信息体现开发过程:三条命令让答辩材料更扎实

毕业设计材料常被质疑“是否独立完成”。将开发痕迹固化在 Git 中:

# 初始化仓库(项目根目录) git init git add . git commit -m "feat: 初始化 ThinkPHP 6.1 项目,配置基础数据库连接" # 实现宿舍分配功能后 git add app/controller/Admin/DormAssignmentController.php app/validate/DormAssignment.php git commit -m "feat(dorm): 实现宿舍分配核心逻辑,含事务与床位校验" # 添加权限控制后 git add app/middleware/RoleCheck.php app/middleware.php git commit -m "feat(auth): 增加楼长数据隔离中间件,支持 building 参数校验"

提示:答辩 PPT 中可截图git log --oneline,展示 3–5 条有意义的提交记录。老师一眼可知开发节奏与模块划分,比“已完成全部功能”更有可信度。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询