设计并实现一个精简的图书管理系统,要求具有图书入库、查询、借书、还书、借书证管理等功能。
基本数据对象
基本功能模块
管理员登录
输入管理员ID, 密码; 登入系统 或 返回ID/密码 错误.
图书入库
图书查询
要求可以对书的 类别, 书名, 出版社, 年份(年份区间), 作者, 价格(区间) 进行查询. 每条图书信息包括以下内容:
( 书号, 类别, 书名, 出版社, 年份, 作者, 价格, 总藏书量, 库存 )
可选要求: 可以按用户指定属性对图书信息进行排序. (默认是书名)
借书
还书
1.输入借书证卡号
显示该借书证所有已借书籍 (返回, 格式同查询模块)
2.输入书号
如果该书在已借书籍列表内, 则还书成功, 同时库存加一.
否则输出出错信息.
借书证管理
增加或删除一个借书证.
采用简单粗暴的MV(视图-模型)这一系统模型,在视图端(浏览器)发送请求,服务器处理这一请求并返回数据,视图接受数据并显示到视图中。
表定义
create table book
(
bno char(8),
category char(10),
title varchar(40),
press varchar(30),
year int,
author varchar(20),
price decimal(7,2),
total int,
stock int,
primary key(bno)
);
create table card
(
cno char(7),
name varchar(10),
department varchar(40),
type char(1),
primary key(cno),
check (type in ('T','S'))
);
create table admin
(
admin_id char(20),
password char(20),
name char(20),
email char(30),
primary key(admin_id)
);
create table borrow
(
cno char(7),
bno char(8),
borrow_date date,
return_date date,
done_by char(20),
foreign key (bno) references book(bno) on delete cascade,
foreign key (cno) references card(cno) on update cascade
);
但是,mysql的check是无用的,使用触发器来实现check功能:
DELIMITER $$
create trigger type_check_triger before insert on card
for each row
begin
if(new.type not in ('T','S'))
then
signal sqlstate '04922'
set message_text = "ERROR: card type not in ('T','S')";
end if;
end $$
DELIMITER ;
首先进入主页,选择(管理员/查询)这两个功能之一。由于普通用户只能进行查询功能,就不需要它们登录了。
这里使用的是html的radio表单:
php脚本根据表单提交选择用户查询界面或者登录界面:
$choseerror="";
$chose="";
if($_SERVER["REQUEST_METHOD"] == "POST"){
if(empty($_POST['q'])){
$choseerror = "必须选择访问身份";
} else {
$chose=$_POST['q'];
if($chose=="admin"){
header("location:login.php");
}else{
header("location:query.php");
}
}
}
?>
登录界面如下图:
选择admin身份,进入登录界面,输入账号和密码:
这个初始的账号是我在创建数据库的时候创建的:
在登录界面的login.php
中,首先和数据库建立连接,这里我使用了mysqli这个mysql拓展来连接。在连接的过程中有一点要注意的是,由于wamp默认了mariadb,所以你在连接的时候要指定mysql服务器的端口号。我就是在连接时找不到我创建的book
数据库,然后在这了卡了很久。
$server_name="localhost";
$username="root";
$password="qazwsx";
$dbname="book";
$conn = new mysqli($server_name,$username,$password,$dbname,'3308');
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
?>
之后再从book数据库中,select
看看是否有表单输入的账户id和pwd,按情况分别处理:
include 'connect.php';
$id=$_POST['account'];
$pwd=$_POST['password'];
$sql_query="select * from admin where admin_id='".$id."' and password = '".$pwd."'";
$sql=$conn->query($sql_query);
$info=mysqli_fetch_array($sql);
if($info==false){
$loginerror = "ID或PWD错误!";
}else{
$_SESSION['admin_id']=$id;
$_SESSION['pwd']=$pwd;
header("location:index.php");
}
账号密码错误提示:ID或PWD错误
登录成功后跳转到index.php
界面。
在index
界面选择所需要执行的功能。
使用一个表单,submit后做出判断,如果是需要的格式就插入到数据库。
所谓对格式做出判断,一是要求非空,二是要求year,num是整形,price是两位小数:
//出版年份
if (empty($_POST["year"]))
{
$yearErr = "必需";
$tbool=false;
}
else
{
$year = test_input($_POST["year"]);
if (!preg_match("/^[0-9]*$/",$year))
{
$yearErr = "只允整数";
$tbool=false;
}
}
//价格
if (empty($_POST["price"]))
{
$priceErr = "必需";
$tbool=false;
}
else
{
$price = test_input($_POST["price"]);
if (!preg_match("/^([0-9]*)+(.[0-9]{1,2})?$/",$price))
{
$priceErr = "decimal(7.2)";
$tbool=false;
}
}
另外要考虑到:如果管理员入库一本馆藏中有的书,那么就不是insert而需要update。于是先做出判断:
$sql_query="select * from book where bno='".$bno."'";
$sql=$conn->query($sql_query);
$info=mysqli_fetch_array($sql);
if($info==false){
//并不存在这一本书
...
}else{
//这本书已经在馆藏中了
...
}
单本插入(无该书馆藏):
插入结果,在命令行中查看:
已经有馆藏了,继续插入:
命令行select
显示新的4本也被入库:
图书信息存在一个文件种,提交文件名:
批量插入后表如下:
同样,在有藏书的情况下再次入库:
批量导入和单本导入的差别并不大,主要涉及到对文件及字符串的处理:
...省略
$filename=$_POST['filename'];
$file=fopen($filename,"r") or exit("无法打开文件".$filename);
while(!feof($file))
{
$line = fgets($file);
$line = test_input($line);
if($line=="") continue;
$line = mb_substr($line,1,mb_strlen($line)-2);
$array = explode(",",$line);
$bno=$array[0];...省略其它赋值
include 'connect.php';
//首先看看是否已经存在了这一本书,如果存在,则update,否则就是insert
$sql_query="select * from book where bno=".$bno."";
$sql=$conn->query($sql_query);
$info=mysqli_fetch_array($sql);
if($info==false){
//并不存在这一本书
...
}else{
//这本书已经在馆藏中了
...
}
...省略
?>
设置一个表单、收集需要的复合查询项。在php中将表单post的值进行处理,此处以price为例。当左/右区间为空时、设置为默认[0,9999.99]。检测值是否符合正则表达式、组装sql语句:
if (!empty($_POST["pricel"]))
{
$pricel = test_input($_POST["pricel"]);
if (!preg_match("/^([0-9]*)+(.[0-9]{1,2})?$/",$pricel))
{
$queryErr = $queryErr."价格左区间应当是decimal(7.2)形式!";
$tbool=false;
}
}
if(!empty($_POST["pricer"]))
{
$pricer = test_input($_POST["pricer"]);
if (!preg_match("/^([0-9]*)+(.[0-9]{1,2})?$/",$pricer))
{
$queryErr = $queryErr."价格右区间应当是decimal(7.2)形式!";
$tbool=false;
}
}
if($pricel > $pricer){
$queryErr = $queryErr."价格左区间应当小于右区间!";
$tbool=false;
}else{
$sql_query=$sql_query." and price between ".$pricel." and ".$pricer." ";
}
查询输入出错:
应当左区间小于右区间且符合格式:
复合查询:
类别为小说、出版年份大于2000,价格小于40,按照出版年份排序:
对于借书,首先判断借书证号是否存在,不存在则输出错误信息:
//测试是否有该借书证
$sql_query="select * from card where cno = '".$cno."'";
//echo $sql_query;
$sql=$conn->query($sql_query);
$info=mysqli_fetch_array($sql);
if($info==false){
//并不存在这一借书证号
$borrowErr.="借书证".$cno."不存在!";
}else{
...
}
然后判断所借的书是否非空,非空则判断是否已经借了这本书,
若没有借这本书,是否还有库存,如果没有库存,最近一次归还日期(实验要求的,我也不知道这个有啥用)
if(!empty($_POST["bno"])){
$bno=$_POST["bno"];
$sql_query="select * from borrow natural join book where cno = '".$cno."' and bno = '".$bno."' and return_date is null";
$sql=$conn->query($sql_query);
$info=mysqli_fetch_array($sql);
//echo $sql_query;
//print_r($info);
if($info==false){
//没有借这本书
$sql_query="select * from book where bno = '".$bno."'";
$sql=$conn->query($sql_query);
$info=mysqli_fetch_array($sql);
if($info==false){
$borrowErr.="该书不存在";
}else{
$tmpstock=$info[8];
if($tmpstock=="0"){
$sql_query="select return_date from borrow where bno = '".$bno."' order by return_date desc";
$sql=$conn->query($sql_query);
$info=mysqli_fetch_array($sql);
$last_re_date = $info[0];
$borrowErr.= "该书库存为0!最近一次归还日期为:
".$last_re_date;
}else{
//从book的stock中减少一本
$sql_query="update book set stock = ".$tmpstock." -1 where bno = '".$bno."'";
//echo $sql_query;
$sql=$conn->query($sql_query);
//向borrow记录插入一本书
$sql_query="insert into borrow values('".$cno."','".$bno."','".date("Y-m-d")."',null,'".$id."')";
//echo $sql_query;
$sql=$conn->query($sql_query);
}
}
}else{
//echo "hello";
$borrowErr.="已经有一本了,给别人留点吧!";
}
}
还书模块的要求与借书模块基本相近。
显示已经借的书籍:
还书(bno=1)之后:
还一本没有借的书:
我们用一个表单来收集一个card tuple所需要的属性,一个单选radio
来选择功能(添加/删除)。
对于插入,判断是否已经存在了一个相同的卡号,如果已存在,则输出错误信息。否则insert
插入:
if($fun=="add"){
if($info==false){
//插入
$sql_query="insert into card values('".$cno."','".$name."','".
$department."','".$type."')";
$conn->query($sql_query);
}else{
//已经存在卡号
$cardErr.="卡号已存在,无法添加!";
}
}
账号已存在:
插入成功:
输入信息不足:
对于删除,也是先查看卡号是否存在。如果存在且该卡号还有未归还的书籍,那么输出错误信息,否则删除。
if($info==false){
//不存在
$cardErr.="没有符合条件的卡号";
}else{
//已经存在卡号,是否有没有还的书
$sql_query="select * from borrow natural join book where cno = '".
$cno."' and return_date is null";
$sql=$conn->query($sql_query);
$info=mysqli_fetch_array($sql);
if($info==false){
//没有没还的书,可以删除
$sql_query="delete from card where cno = '".$cno."'";
$sql=$conn->query($sql_query);
}else{
//还不能删除
$cardErr.="还有未归还的书!";
}
}
查看卡号是否存在:
删除成功:
无法删除一个有借书信息的卡号:
清空session,跳转到首页。
session_start();
$_SESSION = array();
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(),'',time()-42000,'');
}
session_destroy();
header("location:home.php");
?>
总共花了3天,摸索着学html、css、php,最后终于弄出来了这个数据库的期中实验项目,真的困难。
另外代码这个学期不会放出(毕竟要交作业,查重恐怖)
学期结束,代码:https://download.csdn.net/download/baidu_40614951/12549363