PHP宿舍管理系统项目实战

  • 写在前面
  • PHP项目开发标准流程
  • 知识点
  • 项目实现及详细设计
  • 详细设计
    • 前端使用的技术
    • 后端使用的技术
    • 数据库设计
    • 源码解析
      • 系统首页public
      • 管理页面Admin
        • dorm_detail和dorm
        • exchange和exchange_detail
        • home和leave
        • maintain和maintain_detail
        • student和student_detail
        • violation和violation_detail
      • 学生页面Student
        • exchange_add和exchange
        • leave_add和leave
        • maintain和maintain_add
        • violation
      • 教师页面Teacher
        • exchange
        • home
        • leave
        • violation
  • 关键技术
    • 分页功能实现
    • 排序功能
        • 其他功能
    • 编写可维护代码
    • 数据库连接方式PDO
  • 参考资料
  • 心得体会
  • 写在最后

写在前面

这是我的一个答辩项目,我通过对一些开源项目的学习,进一步规范自己的编程开发思想,使其更加系统化,流程化,模块化。本系统若有不足之处,还请指正。

PHP项目开发标准流程

这是我经过大致梳理出来的流程,详细内容还需往后融会贯通。

  • 需求分析
  • 系统分析
  • 系统目标
  • 系统功能结构
    • 业务逻辑结构*
  • 确定开发环境
  • 文件夹结构设计
  • 数据库设计
  • 数据库分析
    • 根据系统分析和系统功能结构,规划出本系统的数据库实体关系E-R图
  • 创建数据库和数据表
  • 编写数据库连接文件
  • 模块化编程
  • 开发总结

知识点

以下仅列出本系统较为重要的知识点:

  • PHP表单实现数据的收集
  • PHP-Cookie和Session的使用
  • PHP - AJAX数据库
  • PHP与MySQL的连接及SQL语句的预处理

项目实现及详细设计

宿舍管理系统功能思维导图:

详细设计

前端使用的技术

  • Jquery
  • AOS Animate On Scroll Library 滚动动画库
  • Bulma CSS框架
  • Font awersome 字体和图标的库
  • JavaScript

后端使用的技术

  • PHP

数据库设计

源码解析

1.在前端方面我主要用了上面所提到的主要技术,具体使用方法可以去CSDN网站找,页面设计参考的网站是来自gitee上的不同前端系统。
2.在后端方面我则是运用PHP语言对信息的交互处理进行设计,这是我的项目目录。

系统首页public

系统首页主要包含用户登录,修改密码,退出账号等页面。
登录页面主要提供学生、老师、宿管等不同用户的登录。
主要功能实现为用户输入用户名,密码,验证码,并选择自己的用户身份进行登录系统。
主要代码如下:login.php

if($_POST){
	    require './_share/_pdo.php';
		$account=$_POST['account'];
		$pwd=$_POST['pwd'];
		$captch=$_POST['captch'];
		$type=$_POST['type'];  //用户类型
		if(strtolower($captch)==strtolower($_SESSION['captcha'])){  //strtolower函数将string中所有的字母字符转换为小写并返回
			$type=$_POST['type'];
			if(!empty($account)&&!empty($pwd)&&!empty($type)){   //登录后获取用户信息
				$sql="select * from t_$type where account='$account' and pwd='$pwd'";
				$result=$pdo->query($sql);
				$row=$result->fetch();   
				$id=$row['id'];
				$name=$row['name'];
				$sex=$row['sex'];
				if(!empty($id)){  
					$_SESSION['user_id']=$id;
					$_SESSION['user_account']=$account;
					$_SESSION['user_type']=$type;
					$_SESSION['user_name']=$name;
					$_SESSION['user_sex']=$sex;
					header("Location: ../$type/home.php");  //
				}else{
					$pwd=null;
					$msg="您输入的账号或密码有误,请重试";
				}
			}
		}else{
			$msg="您输入的验证码有误,请重试";
		}
	}

对于所有用户都提供修改密码功能。我的思路是通过获取旧密码判断用户输入的旧密码是否正确,是否与新密码相同,而后再通过sql语句更新数据库中的密码,这里要注意不同用户类型。
具体代码如下:changepwd.php

if(isset($_SESSION['user_id'])&&isset($_SESSION['user_type'])){
		$user_name=$_SESSION['user_name'];
		$user_id=$_SESSION['user_id'];
		$user_type=$_SESSION['user_type'];
		
		if($_POST){
			
			$old_pwd=$_POST['old_pwd'];
			$new_pwd=$_POST['new_pwd'];
			$check_pwd=$_POST['check_pwd'];
			
			if($new_pwd!=$check_pwd){
				$msg="两次输入的新密码不一致,请核对";
				
			}else{
				require './_share/_pdo.php';
				
				//判断用户输入的旧密码是否正确
				$sql="select pwd from t_$user_type where id=$user_id";
				$result=$pdo->query($sql);
				$pwd=$result->fetch()['pwd'];
				
				if($old_pwd!=$pwd){
					$msg="您输入的旧密码有误,请核对";
					
				}else if($new_pwd==$pwd){
					$msg="旧密码不能与新密码相同";
					
				}else{
					$sql="update t_$user_type set pwd='$new_pwd'";
					if(!$pdo->query($sql)){
						exit("密码修改失败,请重试。".$stmt->errorInfo());
					}
					echo "<script>alert('新密码设置成功。');</script>";
				}
			}
		}
		
	}else{
		//如果用户未登录,跳转到登录界面
		header("Location: ./logout.php");
	}

退出账号则是将PHP session变量都设置为null,并重定向到登录页面。具体代码如下:logout.php

	<?php
	session_start();
	$_SESSION['user_id']=null;
	$_SESSION['user_account']=null;
	$_SESSION['user_type']=null;
	$_SESSION['user_name']=null;
	$_SESSION['user_sex']=null;
	
	$_SESSION['dorm_id']=null;
	$_SESSION['dorm_building']=null;
	$_SESSION['dorm_number']=null;
	
	header('Location: ./login.php');
?>

设计完我的系统首页后,就准备对每个用户的功能进行代码实现,在过程中应该要注意不同用户之间不同功能的交互。

管理页面Admin

在admin目录下,共有12个页面,由于篇幅所限这里主要讲部分重要PHP代码及其原理思路以及如何与前端页面进行交互。

  • dorm_detail
  • dorm
  • exchange_detail
  • exchange
  • home
  • leave
  • maintain_detail
  • maintain
  • student_detail
  • student
  • violation_add
  • violation

dorm_detail和dorm

这两个页面主要实现对宿舍信息的查看和如何向宿舍添加删除学生和设置宿舍长的功能。思路:使用sql语句获取宿舍详细信息,并实现上述功能。
具体代码如下:

			$sql="select a.id,building,number,bed,sex,count from t_dorm as a 
				join (select count(b.id) as count,c.id from t_student_dorm as b right join t_dorm as c on b.dorm_id=c.id group by c.id) 
				as d on a.id=d.id order by ".$sql_order." limit $lim,$page_size";
			$result=$pdo->query($sql);
			$dorm_list=$result->fetchAll();

sql语句中的$ sql_order和$ lim,$ page_size,是实现排序和分页的功能。分页代码在整个系统中多处出现,我会在关键技术中对其进行讲解。这里先对排序功能进行讲解。思路:要对宿舍展现的信息实现排序
代码如下:

exchange和exchange_detail

这里主要实现学生如何申请换宿舍,具体代码如下:

			$sql="select a.id,a.date,admin_response,a.student_id,a.to_dorm_id,d.dorm_id as from_dorm_id,name,account,c.building as to_dorm_building,c.number as to_dorm_number,e.building as from_dorm_building,e.number as from_dorm_number,e.id as from_dorm_id
				from t_student_dorm_exchange as a left join t_student as b on a.student_id=b.id left join t_dorm as c on a.to_dorm_id=c.id left join t_student_dorm as d on d.student_id=b.id left join t_dorm as e on e.id=d.dorm_id
				order by a.id desc limit $lim,$page_size";   	
			$result=$pdo->query($sql);
			$exchange_list=$result->fetchAll();

在写sql语句时会经常发生错误,我的方法就是将其分步骤来写,不断的检查,防止出错。

home和leave

home页面主要实现对用户信息的显示,leave页面主要是查看学生的请假外出。
具体代码如下:

			$sql="select a.student_id,request,date_start,date_end,account,b.name,building,number,c.dorm_id
				from t_student_leave as a join t_student as b on a.student_id=b.id join t_student_dorm as c on b.id=c.student_id join t_dorm as d on c.dorm_id=d.id
				where teacher_response='批准'
				order by date_end desc limit $lim,$page_size"; 
			$result=$pdo->query($sql);
			$leave_list=$result->fetchAll();

后端页面主要是从不同的表中查找出需要的信息,所以sql语句的编写在web开发过程中也非常重要的,决定了系统的效率。这里显示的主要是经过辅导员批准的外出申请。
在前端页面的话,从数据库获取到了信息,关键在于如何处理?并很好的展示在用户面前,这是一个很重要的问题!
思路:使用foreach遍历数组取出不同信息放到不同区域内,需要注意的是需要注意显示的数据格式,以及对于假条时间是否过期的处理。
具体代码如下:

	<?php
							foreach($leave_list as $row):
					?>
								<tr>
									<td>
										<?=$row['account']?>
									</td>
									<td>
										<a href="./student_detail.php?id=<?=$row['student_id']?>">
											<?=$row['name']?>
										</a>
									</td>
									<td>
										<a href="./dorm_detail?id=<?=$row['dorm_id']?>">
											<?=$row['building']?>号楼&nbsp;<?=$row['number']?></a>
									</td>
									<td>
										<?=date('Y-m-d H:i',strtotime($row['date_start']))?>
									</td>
									<td>
										<?=date('Y-m-d H:i',strtotime($row['date_end']))?>
									</td>
								</tr>
								<tr>
									<td colspan="4">
										请假原因:&nbsp;<?=$row['request']?>
										<br>
										&nbsp;										
									</td>
									<td>
										<?php
											if(strtotime($row['date_end'])>time()):
										?>
												<span class="tag is-success">有效</span>
										<?php
											else:
										?>
												<span class="tag is-warning is-light">过期</span>
										<?php
											endif;
										?>
										<br>
										&nbsp;
									</td>
								</tr>
					<?php 
							endforeach;
					?>
  • 在对时间的格式处理中,使用strtotime()函数将任何英文文本的日期时间描述解析为 Unix 时间戳,再使用date()函数格式化时间格式。关于Unix时间戳和date()函数可以去看这两篇文章-

https://www.jb51/article/148360.htm —date函数

https://blog.csdn/harryhare/article/details/88585653?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162462724816780271568479%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162462724816780271568479&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-1-88585653.pc_search_result_cache&utm_term=+Unix+%E6%97%B6%E9%97%B4%E6%88%B3&spm=1018.2226.3001.4187 —Unix时间戳

maintain和maintain_detail

这两个页面主要实现宿管对学生报修信息的查看、回复处理。
具体代码如下:

			$sql="select a.id,a.dorm_id,date,request,admin_response,building,number
				from t_dorm_maintain as a join t_dorm as b on  a.dorm_id=b.id 
				order by a.id desc limit $lim,$page_size";
			$result=$pdo->query($sql);
			$maintain_list=$result->fetchAll();

显示的信息有日期、宿舍楼号及房号、报修内容,是否回复。

//处理表单提交
			if($_POST){
				$maintain_id=$_POST['id'];
				$response=$_POST['response'];

				$sql="update t_dorm_maintain set admin_response=? where id=?";  //更新宿管对学生的回复
				$stmt=$pdo->prepare($sql);   //sql预处理语句
				$stmt->bindParam(1,$response);   //绑定
				$stmt->bindParam(2,$maintain_id);
				if(!$stmt->execute())
				{
					exit("提交失败,请重试。".$stmt->errorInfo());
				}
				header('Location: ./maintain.php');
			}
			
			$maintain_id=$_GET['id'];   //定义浏览器传入的maintain_id
			if(empty($maintain_id)){
				//如果没有$maintain_id参数就返回maintain列表
				header('Location: ./maintain.php');
			}
			
			$sql="select a.id,date,request,admin_response,building,number
				from t_dorm_maintain as a join t_dorm as b on a.dorm_id=b.id 
				where a.id=$maintain_id";
			$result=$pdo->query($sql);
			$maintain_detail=$result->fetch();

前端方面涉及表单提交和数据处理,跟请假页面相似,就不再赘述。

student和student_detail

这两个页面主要是使用sql语句的like子句对学生进行查找以及信息的显示。
具体代码如下:

//student.php
			$keyword=$_GET['keyword'];
			$sql="select student_id,dorm_id,building,number,c.sex,account,c.name as student_name,d.name as class_name
					from t_student_dorm as a right join t_dorm as b on a.dorm_id=b.id right join t_student as c on c.id=a.student_id left join t_class as d on d.id=c.class_id
					where c.name like '%$keyword%' or account like '%$keyword%'
					limit $lim,$page_size";
			$result=$pdo->query($sql);
			$student_list=$result->fetchAll();
//student_detail.php
			$student_id=$_GET['id'];
			$sql="select student_id,dorm_id,building,number,supervisor,c.sex,c.account,c.name as student_name,d.name as class_name,department,e.name as teacher_name
					from t_student_dorm as a right join t_dorm as b on a.dorm_id=b.id right join t_student as c on c.id=a.student_id right  join t_class as d on d.id=c.class_id right join t_teacher as e on d.teacher_id=e.id
					where c.id=$student_id";
			$result=$pdo->query($sql);
			$student_detail=$result->fetch();

写到这里才发现我的sql语句经常会出问题,所以我手绘了一张ER图,然后再去回忆表的连接。

  • left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录
  • right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录
  • inner join(等值连接) 只返回两个表中联结字段相等的行

violation和violation_detail

这里主要是实现学生违规的登记和删除。
具体代码如下:

//登记的思路主要是先选择学生(学生搜索),再对该学生进行违规登记
//处理表单提交violation_detail.php
			if($_POST){
				$student_id=$_POST['id'];
				$date=$_POST['date'];
				$detail=$_POST['detail'];
				
				if(strtotime($date)>time()){
					echo "<script>alert('您选择的违规时间有误,请重试')</script>";
				}else{
					$sql="insert t_student_violation set student_id=? ,date=? ,detail=?";
					$stmt=$pdo->prepare($sql);
					$stmt->bindParam(1,$student_id);
					$stmt->bindParam(2,$date);
					$stmt->bindParam(3,$detail);
					if(!$stmt->execute())
					{
						exit("提交失败,请重试。".$stmt->errorInfo());
					}
					header('Location: ./violation.php');
				}
			}
			
			if(isset($_GET['id'])){ 
				$student_id=$_GET['id'];
				
				//获取学生详细信息
				$sql="select student_id,dorm_id,building,number,c.sex,account,name,supervisor
					from t_student_dorm as a join t_dorm as b on a.dorm_id=b.id join t_student as c on c.id=a.student_id
					where c.id=$student_id";
				$result=$pdo->query($sql);
				$student_detail=$result->fetch();
			}else{
				//如果没有传入学生id,跳转到搜索学生页面
				header("Location: ./student.php?func=违规登记");
			}
//处理表单提交
			if($_POST){
				$voilation_id=$_POST['id'];

				$sql="delete from t_student_violation where id=?";
				$stmt=$pdo->prepare($sql);
				$stmt->bindParam(1,$voilation_id);
				if(!$stmt->execute())
				{
					exit("删除失败,请重试。".$stmt->errorInfo());
				}
			}
			$sql="select a.id,student_id,date,detail,teacher_response,name,account
				from t_student_violation as a join t_student as b on a.student_id=b.id
				order by date desc limit $lim,$page_size";
			$result=$pdo->query($sql);
			$violation_list=$result->fetchAll();

在前端方面还是老样子,具体见源码,有所创新的是我实现了一个使用鼠标点击输入日期的功能,用Javascript实现。输入框id为date,代码如下:

$(function(){
		var options={lang:'ch',format:'Y-m-d'};
		$('#date').datetimepicker(options);
	})

学生页面Student

在student目录下,共有8个页面,由于篇幅所限这里主要讲部分重要PHP代码及其原理思路以及如何与前端页面进行交互。

  • exchange_add
  • exchange
  • home
  • leave_add
  • leave
  • maintain
  • maintain
  • violation

exchange_add和exchange

此处主要实现学生的申请换宿舍的功能。具体代码如下:

//exchange.php
//获取学生信息
			$user_account=$_SESSION['user_account'];
			$user_name=$_SESSION['user_name'];
			$user_id=$_SESSION['user_id'];
			$user_sex=$_SESSION['user_sex'];
			
			if(isset($_SESSION['dorm_id'])&&isset($_SESSION['dorm_building'])){
				//获取原宿舍信息
				$dorm_id=$_SESSION['dorm_id'];
				$dorm_building=$_SESSION['dorm_building'];
				$dorm_number=$_SESSION['dorm_number'];
			}
			
			$sql="select * from t_student_dorm_exchange left join t_dorm on to_dorm_id=t_dorm.id
				where student_id=$user_id order by date desc limit $lim,$page_size";
			$result=$pdo->query($sql);
			$exchange_list=$result->fetchAll();
//获取学生信息
			$user_account=$_SESSION['user_account'];
			$user_name=$_SESSION['user_name'];
			$user_id=$_SESSION['user_id'];
			$user_sex=$_SESSION['user_sex'];
			
			//获取当前宿舍信息
			$dorm_building=isset($_SESSION['dorm_building'])?$_SESSION['dorm_building']:null;
			$dorm_number=isset($_SESSION['dorm_number'])?$_SESSION['dorm_number']:null;
			
			if($_POST){
				//目标宿舍的信息
				$to_dorm_building=$_POST['building'];
				$to_dorm_number=$_POST['number'];
				//换宿舍的原因
				$request=$_POST['request'];
				if($to_dorm_building==$dorm_building&&$to_dorm_number==$dorm_number){
					echo "<script>alert('您当前已在此宿舍')</script>";
				}else{
					require '../public/_share/_pdo.php';
					
					$sql="select id,sex from t_dorm where building='$to_dorm_building' and number='$to_dorm_number'";
					$result=$pdo->query($sql);
					$row=$result->fetch();
					$to_dorm_id=$row['id'];
					if(empty($to_dorm_id)){
						echo "<script>alert('目标宿舍不存在,请核对。')</script>";
					}else{
						$to_dorm_sex=$row['sex'];
						if($user_sex!=$to_dorm_sex){
							echo "<script>alert('该宿舍是".$to_dorm_sex."生宿舍,您无法申请更换。')</script>";
						}else{
							$sql="insert into t_student_dorm_exchange(`student_id`,`to_dorm_id`,`request`) values($user_id,?,?)";
							$stmt=$pdo->prepare($sql);
							$stmt->bindParam(1,$to_dorm_id);
							$stmt->bindParam(2,$request);
							if(!$stmt->execute())
							{
								exit("申请失败,请重试。".$stmt->errorInfo());
							}
							header('Location: ./exchange.php');
						}
					}
				}
			}

其实上面的代码很好理解,先获取目标宿舍的信息,然后与原宿舍进行比较,若不同,则将学生的信息添加到目标宿舍。

leave_add和leave

这里主要实现学生的请假申请和请假外出信息。
具体代码如下:

//leave.php
			$user_account=$_SESSION['user_account'];
			$user_name=$_SESSION['user_name'];
			$user_id=$_SESSION['user_id'];
			
			$sql="select * from t_student_leave where student_id=$user_id order by date_start desc limit $lim,$page_size";
			$result=$pdo->query($sql);
			$leave_list=$result->fetchAll();
			require './view/leave_html.php';
//leave_add.php
			$user_account=$_SESSION['user_account'];
			$user_name=$_SESSION['user_name'];
			$user_id=$_SESSION['user_id'];
			
			if($_POST){
				$date_start=$_POST['date_start'];
				$date_end=$_POST['date_end'];
				$request=$_POST['request'];
				if(strtotime($date_start)<time()){
					echo "<script>alert('起始时间应大于当前时间')</script>";
				}else if(strtotime($date_end)<=strtotime($date_start)){
					echo "<script>alert('返校时间应大于起始时间')</script>";
				}else{
					require '../public/_share/_pdo.php';
					$sql="insert into t_student_leave(`student_id`,`date_start`,`date_end`,`request`) values($user_id,?,?,?)";
					$stmt=$pdo->prepare($sql);
					$stmt->bindParam(1,$date_start);
					$stmt->bindParam(2,$date_end);
					$stmt->bindParam(3,$request);
					if(!$stmt->execute())
					{
						exit("申请失败,请重试。".$stmt->errorInfo());
					}
					header('Location: ./leave.php');
				}
			}

maintain和maintain_add

物业报修功能,需要被安排到宿舍才能进行报修申请,否则无法提交申请。
具体代码如下:

//maintain.php
//获取学生信息
			$user_account=$_SESSION['user_account'];
			$user_name=$_SESSION['user_name'];
			$user_id=$_SESSION['user_id'];
			
			if(isset($_SESSION['dorm_id'])&&isset($_SESSION['dorm_building'])){
				//获取宿舍信息
				$dorm_id=$_SESSION['dorm_id'];
				$dorm_building=$_SESSION['dorm_building'];
				$dorm_number=$_SESSION['dorm_number'];
				
			$sql="select * from t_dorm_maintain where dorm_id=$dorm_id order by date desc limit $lim,$page_size";
			$result=$pdo->query($sql);
			$maintain_list=$result->fetchAll();
//maintain_add.php
				//获取学生信息
			$user_account=$_SESSION['user_account'];
			$user_name=$_SESSION['user_name'];
			$user_id=$_SESSION['user_id'];
			
			if(isset($_SESSION['dorm_id'])&&isset($_SESSION['dorm_building'])){
				//获取宿舍信息
				$dorm_id=$_SESSION['dorm_id'];
				$dorm_building=$_SESSION['dorm_building'];
				$dorm_number=$_SESSION['dorm_number'];
				
				if($_POST){
					require '../public/_share/_pdo.php';
					$sql="insert into t_dorm_maintain(`dorm_id`,`request`) values($dorm_id,?)";
					$stmt=$pdo->prepare($sql);
					$stmt->bindParam(1,$_POST['request']);
					if(!$stmt->execute())
					{
						exit("申请失败,请重试。".$stmt->errorInfo());
					}
					header('Location: ./maintain.php');
				}
				
				require './view/maintain_add_html.php';
			}else{
				//如果获取宿舍信息失败
				header('Location: ./view/maintain.php');
			}
		}

violation

显示学生违规记录。
具体代码如下:

//获取学生信息
			$user_account=$_SESSION['user_account'];
			$user_name=$_SESSION['user_name'];
			$user_id=$_SESSION['user_id'];

			$sql="select * from t_student_violation where student_id=$user_id order by date desc limit $lim,$page_size";
			$result=$pdo->query($sql);
			$maintain_list=$result->fetchAll();

教师页面Teacher

在teacher目录下,共有4个页面,由于篇幅所限这里主要讲部分重要PHP代码及其原理思路以及如何与前端页面进行交互。

  • exchange
  • home
  • leave
  • violation

exchange

教师端实现对学生换宿的审批功能,这里需要展现学生换宿的具体信息和原因,同时看到目标宿舍的居住情况,以及宿管意见。
具体代码如下:

//处理表单提交
			if($_POST){
				$leave_id=$_POST['id'];
				$response=$_POST['response'];
				if(!empty($leave_id)&&!empty($response)){
					$sql="update t_student_dorm_exchange set teacher_response=? where id=?";
					$stmt=$pdo->prepare($sql);
					$stmt->bindParam(1,$response);
					$stmt->bindParam(2,$leave_id);
					if(!$stmt->execute())
					{
						exit("提交失败,请重试。".$stmt->errorInfo());
					}
					header('Location: ./exchange.php');
				}
			}
			$sql="select a.id,a.date,a.request,a.admin_response,a.teacher_response,b.account,b.name as student_name,c.name as class_name,d.building,d.number,d.bed,g.count
				from t_student_dorm_exchange as a join t_student as b on a.student_id=b.id
					join t_class as c on b.class_id=c.id
					join t_dorm as d on a.to_dorm_id=d.id
					join (select count(e.id) as count,f.id from t_student_dorm as e right join t_dorm as f on e.dorm_id=f.id group by f.id) as g on g.id=d.id
				where c.teacher_id=$user_id
				order by a.id desc limit $lim,$page_size";
			$result=$pdo->query($sql);
			$exchange_list=$result->fetchAll();

home

教师信息显示。具体代码如下:

//获取教师信息
			$user_account=$_SESSION['user_account'];
			$user_name=$_SESSION['user_name'];
			$user_id=$_SESSION['user_id'];
			
			//获取班级信息
			require '../public/_share/_pdo.php';
			$sql="select * from t_class where teacher_id=$user_id";
			$result=$pdo->query($sql);
			$class_list=$result->fetchAll();
			require './view/home_html.php';

leave

教师对学生外出请假的审批,具体代码如下:

//处理表单提交
			if($_POST){
				$leave_id=$_POST['id'];
				$response=$_POST['response'];
				if(!empty($leave_id)&&!empty($response)){
					$sql="update t_student_leave set teacher_response=? where id=?";
					$stmt=$pdo->prepare($sql);
					$stmt->bindParam(1,$response);
					$stmt->bindParam(2,$leave_id);
					if(!$stmt->execute())
					{
						exit("提交失败,请重试。".$stmt->errorInfo());
					}
					header('Location: ./leave.php');
				}
			}
			
			$sql="select a.id,a.date_start,a.date_end,a.request,a.teacher_response,b.account,b.name as student_name,c.name as class_name
				from t_student_leave as a join t_student as b on a.student_id=b.id join t_class as c on b.class_id=c.id
				where c.teacher_id=$user_id
				order by date_start desc limit $lim,$page_size";
			$result=$pdo->query($sql);
			$leave_list=$result->fetchAll();

与此同时,还需在前端页面控制是否批准学生的请假,具体代码如下:

<tr>
				<?php
					$teacher_response=$row['teacher_response'];
					if(empty($teacher_response)):
				?>
					<td colspan="3">
						&nbsp;<br>&nbsp;
					</td>
					<td colspan="1">
						待回复:
					</td>
					<td colspan="2">
						<div class="buttons">
							<a class="button is-small is-outlined is-success" onclick="checkYes(<?=$row['id']?>,'<?=$row['student_name']?>')">批准</a>
							<a class="button is-small is-outlined is-dark" onclick="checkNo(<?=$row['id']?>,'<?=$row['student_name']?>')">否决</a>
						</div>
					</td>
				<?php
					else:
				?>
					<td colspan="3">
						&nbsp;<br>&nbsp;
					</td>
					<td colspan="1">
						已回复:
					</td>
					<td colspan="2">
						<?=$teacher_response?>
					</td>
				<?php
					endif;
				?>
</tr>

violation

教师对学生违规情况的详情了解,具体代码如下:

//处理表单提交
			if($_POST){
				$violation_id=$_POST['id'];
				$response="已读";
				if(!empty($violation_id)){
					$sql="update t_student_violation set teacher_response=? where id=?";
					$stmt=$pdo->prepare($sql);
					$stmt->bindParam(1,$response);
					$stmt->bindParam(2,$violation_id);
					if(!$stmt->execute())
					{
						exit("提交失败,请重试。".$stmt->errorInfo());
					}
					header('Location: ./violation.php');
				}
			}
			
			$sql="select a.id,detail,date,account,teacher_response,b.name as student_name,c.name as class_name
				from t_student_violation as a join t_student as b on a.student_id=b.id join t_class as c on b.class_id=c.id
				where c.teacher_id=$user_id
				order by date desc limit $lim,$page_size";
			$result=$pdo->query($sql);
			$violation_list=$result->fetchAll();

关键技术

每一部分采用的技术,可以使用部分源代码说明,尽量将课程中学过的技术都用上。必须对每一部分的技术和知识点加以说明。自己认为比较关键的、得意的地方,文字说明,可辅助代码。每个作品必须选取二十行以上的关键代码逐句进行解释.

分页功能实现

在许多页面都有分页功能,这主要是为了使页面更加简洁,便于用户查看信息。同时实现翻页功能,虽然这两者是一体的…
实现思路:比如宿舍详细信息页面,首先我们要设置每页显示的行数,然后查询数据库里的宿舍总数,求出最大页面数,同时还需考虑页面的几种情况:是否为空,再确定页数的最大值和最小值,防止出现错误。
具体代码如下:

//处理分页
			$page_size=5; //每页显示的行数
			$result=$pdo->query("select count(*) from t_dorm"); //  获取数据库中的宿舍数量
			$count=$result->fetch()[0];  
			$max_page=ceil($count/$page_size);  //最大页面数  celi函数向上舍入为最接近的整数
			$page=isset($_GET['page']) ? intval($_GET['page']) : 1;  //定义变量由浏览器传入
			$page=$page>$max_page ? $max_page : $page;//最大值
			$page=$page < 1 ? 1 : $page;//最小值处理
			$lim=($page -1)*$page_size;//限制条件处理

还需要注意的是,在数据库中查找信息的过程中不要忘记加入limit条件,具体可以去看一下MySql数据库的菜鸟教程。到这里我们后端已经写完,接下来就是如何在前端显示这个效果。具体代码如下:

<?php
		if($max_page>1):    //分页功能
		?>
			<br>
			<nav class="pagination is-centered" role="navigation" aria-label="pagination">
			  <a class="pagination-previous has-background-white" href="./dorm.php?page=1">首页</a>
			  <a class="pagination-previous has-background-white" href="./dorm.php?page=<?=$page-1; ?>"><</a>
			  <ul class="pagination-list">   
					<?php             //新建变量循环并判断,若是当前页面则点亮页面标签,不是则为空白。
						for($p=1;$p<=$max_page;$p++):  
							if($p==$page):
					?>
								<li><a class="pagination-link is-current" href="./dorm.php?page=<?=$p?>"><?=$p?></a></li>							
					<?php
							else:
					?>
								<li><a class="pagination-link has-background-white" href="./dorm.php?page=<?=$p?>"><?=$p?></a></li>
					<?php
							endif;
						endfor;
					?>
			  </ul>
			  <a class="pagination-next has-background-white" href="./dorm.php?page=<?=$page+1; ?>">></a>
			  <a class="pagination-next has-background-white" href="./dorm.php?page=<?=$max_page; ?>">尾页</a>
			</nav>

代码写到这里,分页功能也算是写完了。其他页面的分页功能都是一样,所以要融会贯通,便可解决大部分问题。

排序功能

排序功能的实现思路在于先获取需要排序的信息,再在sql语句中进行排序(ASC\DESC)
举例(dorm.php)
代码如下:

//处理排序
			//默认order by building
			$sql_order="building";
			if(isset($_GET['order'])){
				$order=$_GET['order'];  //浏览器传入需要排序的信息,针对不同信息类目进行升降排序
				switch($order){
					case "building_desc":   //降序
						$sql_order="building desc";
						break;
					case "number":
						$sql_order="number";  //默认升序
						break;
					case "number_desc":
						$sql_order="number desc";
						break;
					case "bed":
						$sql_order="bed";
						break;
					case "bed_desc":
						$sql_order="bed desc";
						break;
					case "count":
						$sql_order="count";
						break;
					case "count_desc":
						$sql_order="count desc";
						break;
				}
			}
//得到之后则把$sql_order代入sql语句进行查询,具体代码如下:
			$sql="select a.id,building,number,bed,sex,count
				from t_dorm as a join 
				(select count(b.id) as count,c.id from t_student_dorm as b right join t_dorm as c on b.dorm_id=c.id group by c.id) as d on a.id=d.id
				order by ".$sql_order." limit $lim,$page_size";
			$result=$pdo->query($sql);
			$dorm_list=$result->fetchAll();

其他功能

  • 使用date()函数
  • 使用UNIX时间戳
  • PHP会话控制(在管理页面中有详细解释)
    在login.php中,就使用了会话控制,步骤是开始会话->注册会话变量$_SESSION来存储信息->使用会话变量->注销变量并销毁会话(logout.php)

编写可维护代码

在以往的编写代码的过程中,习惯于将PHP代码和前端写到一起,在看到许多优秀的博主写的代码后,我也将所编写的代码视图层和逻辑层分开来。

数据库连接方式PDO

之前用的都是mysqli,但我推荐大家用pdo,因为pdo的强大之处是显而易见的,支持多种数据库,还有参数绑定是特色。

参考资料

  • 各大高校宿舍管理系统
  • PHP和MySQL Web开发(Fourth Edition) by luke Welling

心得体会

在完成这次期末答辩项目的过程中,我最大的收获就是,自己编写一个完整软件开发的项目更加清晰了,同时我的收获不仅仅只停留在写代码的思路上,关键更在于编写可维护的代码,目的在于使代码更加的标准化。即以下几点:

  • 定义命名惯例
  • 使代码易读
  • 使标识符易记
  • 代码注释
  • 项目文档化

除此之外,在设计的过程中,数据库的创建决定了整个系统功能交互的效率,若是表没有设计好需要的字段,就会使整个系统显得复杂低效。
最后就是我经过学习了解到我的这个项目还存在许多需要改善的地方,而在不断的迭代升级中,会发现如果没有一个很好的版本控制方法,项目的进程将会面临许多问题,我上网搜索了一下,找到了两个版本控制产品,分别使CVS和Bitkeeper,在这里就不详细介绍,总而言之,在web项目这条道路上我还有很长很长的路要走,技术日新月异,但我追求知识的脚步从未停止。

写在最后

更多推荐

PHP宿舍管理系统项目实战