网络技术科研与创新能力实践
题 目: 网上订餐系统
学 院: xxxx 学院
专业名称: xxxxxx
班级学号: xxxxxx
学生姓名: xxx
指导教师: xxxxx
2014 年 12 月 1 日
摘要
随着网络的普及,人们也通过各类网上的系统来方便日常的生活,此系统就是基
于 B/S 模式开发的网上订餐系统。订餐系统为用户提供注册及登入功能;当成功注册
为网站的用户,用户即可通过本系统进行订餐,其中包括菜品订购、查看或修改订单、
提交订单、查阅过往订单。同时,订餐系统为餐饮管理者提供系统登入、用户所购订
单查看、菜品信息管理。本文将从用户和餐饮管理者的角度对本系统进行详细的介绍。
此系统是基于 HTML、DIV+CSS、PHP、JavaScript 语言开发的一套订餐系统。
系统实施包括三个阶段(前期、中期、后期),实施工作前期包括系统过程图设计、
数据库设计、MVC 开发模式图设计、XML 文档设计,实施工作中期包括系统代码编
写、系统网页设计、系统功能优化等,实施工作后期主要包括系统的功能测试。
关键字:系统、注册、管理、订购
目 录
前言 ................................................................ 1
第一章 网上订餐系统需求分析.......................................... 2
网上订餐系统任务概述............................................ 2
网上订餐系统的设计要求.......................................... 2
网上订餐系统功能流程........................................ 2
网上订餐系统功能流程分析.................................... 2
网上订餐系统功能过程图.......................................... 3
网站注册、订餐过程图........................................ 3
管理员操作管理过程图........................................ 4
网上订餐系统需求总结............................................ 5
第二章 网上订餐系统数据层设计介绍.................................... 5
系统数据层简述.................................................. 5
网上订餐系统数据层.............................................. 5
数据层-----数据库表格设计简述............................... 5
数据层-----数据库表格设计详述............................... 5
数据层-----XML 文件设计简述.................................. 8
数据层-----XML 文件设计详述.................................. 8
网上订餐系统数据层总结........................................... 9
第三章 网上点餐系统管理层功能设计与实现.............................. 11
系统管理层简述................................................... 11
网上订餐系统管理层功能设计与实现................................. 11
管理层-----管理员登入功能三层模式设计........................ 11
管理层-----管理员登入功能实现................................ 12
管理层-----管理员登入功能图示................................ 15
管理层-----管理员操作功能三层模式设计........................ 16
管理层-----管理员操作功能实现................................ 17
管理层-----管理员操作功能图示................................ 22
网上订餐系统管理层功能总结....................................... 25
第四章 网上订餐系统用户层功能设计与实现.............................. 25
系统用户层简述................................................... 25
网上订餐系统用户层功能设计与实现................................. 25
用户层-----用户登入、注册功能三层模式设计.................... 25
用户层-----用户登入、注册功能实现............................ 25
用户层-----用户登入、注册功能图示............................ 30
用户层-----用户操作功能三层模式设计.......................... 31
用户层-----用户操作功能实现.................................. 34
用户层-----用户操作功能图示.................................. 45
网上订餐系统用户层功能总结....................................... 47
第五章 网上订餐系统项目总结.......................................... 47
参考文献.............................................................. 48
附 录 .................................................................. 49
前言
随着信息和网络技术的发展和进步,高效便捷的系统服务为越来越多的人们所追
求,尤其的基于 B/S 模式的服务系统,越来越受到广大用户们的欢迎。这种模式的好
处在于,有更加良好的交互界面、有更加便捷的操作体验、有更加灵活高效的系统,
使得开发者可以及时的更新系统的功能和不断提升系统的性能,使得用户有更好的交
互体验。正是由于这种背景,开发了此套基于 B/S 模式的网上订餐系统。
网上订餐已成为时下较为普遍和流行的一种电商模式,尤其是在我们的校园和白
领人士上班的地方,这样的需求较为普遍。不方便外出就餐的人们通过各类的订餐网
站进行网上订餐,客户提供送餐地址和联系电话,卖家则通过系统反馈的信息来给客
户提供相应的服务。本系统也是基于这样的一种思想,来实现相应的功能。当然,就
一个完整的系统来说,我们需要将该系统进行划分,分为用户层面的和管理者层面。
对于用户层面,我们需要对用户渴求的一些基本功能和系统本身的需求进行结合,来
考虑最终的系统用户层面的功能需求。而对于管理者层面我们需要更加考虑到安全性
和功能性的二者结合,因为管理者层需要接触权限更高的一些操作,如一些重要的数
据库表单的 CRUD 操作以及可能的客户信息等。故本系统将功能层面的操作分为客
户层面和管理者层面,使得系统更加的完善、友好。
当然对于 B/S 模式,我们需要更多的考虑到的是系统的安全性和健壮性,对于客
户可能的不合法操作需要进行相应的出错处理。本系统对于安全性方面主要是基于合
法用户的在线监测,而对于健壮性方面,系统对于用户可能出现的错误操作都进行了
相应的出错处理,屏蔽了一些可能存在的非法操作,一个提供了系统的健壮性,另一
方面也提高了客户的交互体验。当然,对于成熟的 B/S 模式系统,有更加完善的系统
级的安全保护和各种错误处理机制,所以,随着今后各种 B/S 模式系统的推出,会有
更多的系统安全解决方案,使得 B/S 模式系统更加安全。
总之,B/S 模式会是今后较为流行的一种开发模式,各类高体验的系统也会建立
在这种模式上,给予客户更加方便快捷的体验,也减轻了客户本地系统压力。今后我
们只要点击浏览器,就可以登入各类系统进行操作。
第一章:网上订餐系统设计需求分析
网上订餐系统的任务概述
网上订餐系统是基于 B/S 模式开发一种用户订餐系统,本系统需要实现的功能主
要功能有以下的几个方面。首先,系统最为基础的功能是要实现用户的注册、用户的
系统登入功能,其次,系统需要为用户提供订餐服务,其中包括点击订餐、购物篮的
显示、购物篮信息的修改、提交订单等功能;同时也提供给用户查询以往订餐信息的
操作,以及修改密码的操作。再有,系统需要为管理者或者我们俗称为餐饮经营者提
供管理界面,包括订单接收、菜餐信息的修改等功能。通过对系统以上功能的整合分
析,并结合在代码实施阶段的功能调整,搭建起一个完整的网上订餐系统。
网上订餐系统的设计要求
网上订餐系统功能流程
第一步:进入订餐网站,如需点餐,用户首先需要注册,用户可以点击页面右上
方“注册”按钮进入注册页面。
第二步:请按指定格式填写用户的用户名、订餐联系手机号、电子邮箱等个人资
料,并设置密码,以便下次订餐时凭借输入电子邮箱(或手机号)和密码快速登录。首
次订餐用户需仔细阅读《用户协议》,点击“同意”接受用户协议后方可继续下一步。
第三步:填写送餐地址请选择用户所在城市,并填写用户的详细地址信息以完成
注册。用户输入的详细地址会保存在用户的地址簿中方便用户下次订餐提交。
第四步:浏览菜单点餐选择用户喜爱的餐点,输入份数,然后选择“立即订购”。
用户可以在右侧“我的订单”中看到用户的点餐内容和金额。
第五步:确认送餐信息并复核订单,系统将分别罗列出用户的送餐信息以及用户
的订单,用户可在此再次复核用户的地址信息和订单。点击“提交”即可完成用户的首
次订餐!
网上订餐系统功能流程分析
分析一:根据以上对于本订餐系统功能流程的描述,可以看到,本系统仅对注册
用户提供订餐服务,而对于非注册用户不提供相应的服务,那么系统在响应相应的订
餐动作时,需要作出判断,并向客服反馈!即若用户在已登入的情况下订餐,则更新
购物篮信息,否则提示尚未登入,无法订餐。
分析二:对于用户注册时所提供的手机号,邮箱账号等信息,我们不将其作为登
入的 ID 使用,参考目前多数网站的做法,我们需要用户提供唯一标示身份的 ID,那
么为了避免冲突,我们将在注册时进行检索,来防止用户提供与其他用户相同的 ID
号,并提示用户修改 ID,从新注册。
分析三:本系统提供的用户协议也是用户订餐的操作事项,所以我们将此功能调
整为用户每次进行订餐时,都需要对协议进行勾选,否则无法提交订单。
网上订餐系统功能过程图
网站注册、订餐过程图:(图 )
图
以上过程图简单的表述了订餐和注册的一个过程图,根据对系统功能流程的介绍
下下下下\下下下下下
下下下下下下/下下
下下下下下下
下下下下 下下下下
下下下下下下
下 下
下下下下下下下下
下下下
下下下下下下 下
下下下下下下
下下下下
下下下下下下下下下
下下下下下
下
下
下下
下下下下下下
下下下下
下下下下下下下
下
下
下下
下下下下下下下下下
和分析可以看出,在进行注册和订餐时,都需要进行完整性和合法性校验,通过规则
的校验才能最终提交。
管理员操作管理过程图(图 )
图
以上过程图为管理员操作过程图,反应了管理员对于客户反馈的订单信息进行相
应的处理操作过程,以及对于本餐饮店的一些日常店铺的管理和维护工作的操作过程。
网上订餐系统需求总结
下下下下下下下
下下下下下下
下下下下下
下下下下
下
下下下下
下
下下下下
下下
下下下下下下
下下下下下下下下 下下下下下下下下
下下下下下下下
下下下下下下
下
下
下下下下
下下
下下下下下下下下
下下
下下下下
根据以上的分析,我们将网上订餐系统的需求归纳为以下的几个方面:
1、客户注册需求
2、客户和管理员登入需求
3、客户订餐和提交订单需求
4、管理员处理订单需求
5、管理员修改菜品信息需求
6、客户个人信息修改需求
以上为该系统所总结出的六大功能需求,我们将在项目的实施阶段一一对其进行
功能实现和完善。
第二章:网上订餐系统数据层设计介绍
系统数据层简述
作为一套订餐系统,避免不了系统和用户进行数据的交互,用户需要向系统提交
输入的数据信息,系统需要对用户的信息进行分析、识别和处理。所以数据层的设计
对于一套系统来说是不可避免的,而且也是重中之重的。一个好的底层数据的存储设
计,对于系统的运行速度、执行效率、人机交互等这些方面都有很大的影响。存储数
据的方式也无外乎为三种,写内存、写数据库、写文件;这三类存储方式有其各自的
优缺点,对于写内存型存储方式,主要用于即时性的数据,这类数据不要求记录也不
是很重要,但在系统的运行中需要不断的进行读取调用;而对于写文件型存储,这类
存储的信息多为配置信息,但也可根据系统需求进行合理使用,本系统即将用户购物
篮信息和订单信息写成 XML 文件,使得系统更加高效;对于数据库存储,保存的多
为需要进行快速检索和定位的信息,当然这些数据也是长期存储的,并且对于数据间
具有关联的数据多运用数据库进行存储,这样可提高数据可维护性和数据的完整性。
网上订餐系统数据层
数据层-----数据库表格设计简述
我们将数据库表格分为三类表,分别为管理员表,用户表,菜单表。其中管理员
表有两张,一张维护着管理员的登入名和密码,以及邮件信息;另一张维护着管理员
登入时为进一步确定身份而进行的问题验证机制所设定的问题信息表。而对于用户表
和菜单表都仅有一张表,分别维护着用户的基本信息和菜品对应的基本信息。
数据层-----数据库表格设计详述
管理员表主要存储着管理员的信息,管理员登入名和管理员的登入密码,以及管
理员的邮箱地址;还有就是用于管理员登入时进行二次验证的问题。两张表的名字分
别为 admin_infor_data 和 admin_question_data。
表 admin_infor_data 设计如下:
表 admin_question_data 设计如下:
以上为 admin 的两张表格的设计,初始的数据为:
Insert into Admin_infor_data(admin_name,admin_password,admin_email) values(' 小 米
',md5('12345'),'xiaomi@');
insert into Admin_question_data(admin_name,admin_question,admin_answer) values(' 小
米','我喜欢的花是?','百合');
初始的管理员为小米,密码为 12345,且使用 MD5 加密存储,提高安全性。并初始
化需要验证回答的问题为“我喜欢的花是?”,答案是:“百合”。
用 户 表 和 菜 单 表 分 别 维 护 者 用 户 和 菜 品 的 信 息 , 两 张 表 分 别 命 名 为
user_infor_data 和 dishes,以下给出两张表的设计:
表 user_infor_data 设计如下:
表 dishes 设计如下:
Field Type Null Key Default Extra
Admin_id Int(10)unsigned NO PRI NULL Auto_increment
Admin_name Varchar(64) NO NULL
Admin_password Varchar(512) NO NULL
Admin_email Varchar() NO NULL
Field Type Null Key Default Extra
Admin_name Varchar(64) YES NULL
Admin_question text NO NULL
Admin_answer text NO NULL
Field Type Null Key Default Extra
User_id Int(10)unsigned NO PRI NULL Auto_increment
User_name Varchar(64) NO NULL
User_password Varchar(512) NO NULL
User_telephone Varchar(32) NO NULL
User_email Varchar(128) NO NULL
User_address text NO NULL
对于用户表,主要存储着用户的订餐电话,用户的送餐地址,用户 Email,用户的登
入名和密码,一样密码也采用 MD5 加密后存储,提供数据库的安全性。
对于菜单表,主要存储菜单的菜品名、菜品的价格、菜品所属的菜系、菜品图片所存
储的路径。(图 )
图
本系统采用的数据库为 MYSQL 数据库,本类型数据库具有小巧,易维护等特点,
多适合于小中型网站的数据库选择。且该类型的数据库免费提供给开发者使用,对于
学习型的开发者来说是较好的一种学习选择。并且,这种数据库可以支持各种语言的
访问,如 Java、PHP 等语言对其都有较好的支持。尤其是 PHP 对其有较成熟函数支
持,提供较多操作数据库的函数。一般,我们将这些函数封装成操作数据库的类,后
续会进行详细的介绍。
数据层-----XML 文件设计简述
Field Type Null Key Default Extra
Dishes_id Int(10)unsigned NO PRI NULL Auto_increment
Dishes_name Varchar(64) NO NULL
Dishes_value Int(10)unsigned NO NULL
Dishes_kind Varchar(64) NO NULL
Dishes_path text NO NULL
在系统的数据层方面,我们没有全部采用数据库表形式存储,尤其对于要经常改
写的一些底层数据,我们将其设计成一定格式的 XML 文件。这里需要引入的一个技
术即为 DOM 编程技术,该技术可以将一定格式的 XML 文件转化为一棵 XML 文件
树,文件树维护着 XML 文件中的各个节点信息。通过 DOM 提供一些操作函数和类
内置变量可以利用我们方便地操作一棵 XML 文件树,达到以一定的格式读写 XML
文件树的目的。基于 XML 文件的存储速度快,易于操作的优点,我们将用户的购物
篮中的信息写成一个 XML 文件以及将用户提交的订单也写成一个 XML 文件。
数据层-----XML 文件设计详述
将用户购物篮信息保存成 XML 文件,我们需要考虑到每一个用户维护着自身的
购物篮信息,而这些购物篮信息又都存储在同一个 XML 文件中,所以如何区分存储
是设计 XML 文件的主要内容。同时对于存储的信息的选择也非常的关键,这里的设
计主要是要防止数据的冗余存储。
我们将用户存储购物篮信息的 XML 文件命名为: 文件,其设计
如下(图 )
图
可以看到,此 XML 文件的根节点为 order_dishes,每个 user_id 维护了一个 ID 属
性,用于区分不同用户提交的购物篮信息,同时 user_id 为根节点的子树下维护着所
订购的菜品的名字和份数信息。其实构建了四层子树的文件结构(图 )。
图
将用户提交的订单信息保存到 XML 文件中,也是依然需要对不同用户提交的信
息进行区分,而且,由于系统提供以往订单查询的功能,所以对于提交的订单,我们
需要给每天的订单加上相应的时间戳,来区别不同时间所提交的订单信息。再有,对
于用户提交的订单,我们需要加上相应的标准位,来确定本条记录是否已经处理,及
餐厅是否已经接受订单,若已接受及不再给餐厅进行处理。
我们将接受订单信息的 XML 文件命名为: 文件,其设计
的结构如下(图 )
图
这里将 XML 的根节点设为 submit_order,order_time 作为其子节点,在其属性
Order_dishes
user_id
Dishes_name
Dishe_num
...
id
name
value
time 标记上描述着订单提交的日期,那么这一天提交的所有订单都会存储在这个节点
下。同上,使用 order_id 来区分不同的用户提交的订单信息,订单信息中描述着订单
的菜品、菜品份数、价格、送餐地址、联系电话、送餐时间等。其中有个 state 的子
节点用于标记此份订单是否已被处理,未被处理显示“on”,已被处理显示“off”。同样
这里也维护着一棵五层模式的 XML 文件树(图 )
图
网上订餐系统数据层设计总结
以上介绍了网上订餐系统的数据层设计,数据层的设计是通过写内存和写文件结
合的方式进行的,一些需要进行多次更改的数据,如用户购物篮中的数据以及用户多
次提交订单的数据,我们使用写文件的方式,即上述的写 XML 文件的方式进行数据
的录入和获取。而对于不需要经常进行更改的数据这里使用数据库进行存储,即如上
述的菜品信息以及管理员、用户信息。这样的设计可以提高系统的执行效率,提高系
统的运行速度,同时也贴合系统的需求。总之,该数据层的设计达到了对于各类数据
的存储与提高各类数据处理效率的目标。
第三章:网上点餐系统管理层功能设计与实现
Submit_order
Order_time
Order_id
Order_name address price time telephone state
time
id
name
Order_num
value value value value valuevalue
系统管理层简述
管理层,作为一块功能层的总称,在大多数的系统中都会有这一功能模块,其在
系统中的主要作用是维护系统的各类数据。通俗的讲,管理层也作为系统的一类用户,
也管理着一类数据,其区别在于系统所授予数据操作的权限不同,管理层所感兴趣的
需求与一般用户的需求也不同,所以其功能上需要作为一个独立的模块进行分析。
网上订餐系统管理层功能设计与实现
管理层-----管理员登入功能三层模式设计
管理员登入根据三层模式的特点,将功能模块分为视图层、处理层、数据层,在
此功能上,视图层上主要是用于接受管理员的登入请求,视图层的界面分为登入界面
()、二次问题验证界面()。
而对于处理层分为数据处理()、数据服务(用于处理提
交到后台的合法数据)(),数据处理页面会调用(call)数
据服务中的函数,来得到相应的功能函数。总之,数据处理调用功能函数,根据函数
返回的结果来判断是否为合法登入。(设计见图 )
图
管理层-----管理员登入功能实现
下下下下下下下下下mvc下下下
下下下
下下下
下下下
database
Login
Restaurant_login_process.
php
Restaurant_login_service.
php
sub
mi
t
call
call
operation
illegal
legal
illeagal
legal
Restaurant_login_process.
php
sub
mi
t
call
管理员登入功能的实现主要在于通过管理员提交的数据和后台的数据进行校验,
来达到检验管理员身份是否合法的目的。
管理员登入数据处理代码,即位于 中的代码,这里
对数据进行初步的校验和分析,主要对数据完整性和合法性进行检验。
登入功能第一层校验,用户名密码校验,其代码如下:
if(!empty($_POST['loginname'])&&!empty($_POST['password'])&&!empty($_POST['che
ckcode'])){//查看登录数据的完整性
$login_name=$_POST['loginname'];
$password=$_POST['password'];
$check_code=$_POST['checkcode'];//接收登入信息(登录名、密码、验证码)
}else{
header("location:
exit();
}
if(!empty($_SESSION['checkline'])){
$check_line=$_SESSION['checkline'];//获取验证码
}
if(!empty($_POST['login_model'])){
$login_modle=$_POST['login_model'];//获取登入模式(一般用户、管理员)
}
if($check_line==$check_code){//校验验证码
$res=$login_service->check_password($login_name,$password,$login_modle);
if($res){//调用 check_password 函数检验密码,正确返回 true,错误返回 false
if($login_modle=="admin"){
$_SESSION['admin_name']=$login_name;//将登入名写入 session 中
$_SESSION['login_one']=1;///用于标记第一层检验通过
header("location:");//验证通过,跳转至第二层
exit();
}
}else{
header("location:
exit();
}
}else{//验证码错误,返回错误信息
header("location:
exit();
}
登入功能第二层校验,管理员问题校验,其代码如下:
if(!empty($_GET['question_check'])){//提交是数据来自问题校验功能模块
if(!empty($_POST['login_answer'])&&!empty($_POST['checkcode'])){//完整性校验
$check_code=$_POST['checkcode'];
if($_SESSION['checkline']==$check_code){//检验验证码
$login_name=$_SESSION['admin_name'];
$login_answer=$_POST['login_answer'];//接收校验数据
$res=$login_service->check_answer($login_answer, $login_name);
if($res){//调用 check_answer 函数,正确返回 true,错误返回 false
$_SESSION['login_two']=1;//管理员登入成功标记,写入 session 中
header("location:");
exit();//登入成功,跳转至管理员界面
}else{//答案错误,返回错误信息
header("location:
exit();//
}
}else{ //验证码错误,返回提示信息
header("location:
exit();
}
}else{
header("location:
exit(); }//验证信息不完整,返回错误信息
}
check_password($login_name,$password,$login_modle)函数代码如下:
public function check_password($login_name,$password,$login_model){
$mysql=new Mysqli_stmt_h();//新建一个数据库操作类对象
if($login_model=="admin"){//构造管理员登陆模式 SQL 语句
$sql="select admin_password from Admin_infor_data where
admin_name='".$login_name."'";
}
$arr=$mysql->oper_query($sql);//执行返回数据库中的密码
$mysql->conn_close();//关闭数据库连接
if($arr[0][0]==md5($password)){//与用户提交的密码进行对比
return 1;//相同返回 1
}else{
return 0;//不同返回 0
}
}
check_answer($login_answer, $login_name)函数代码如下:
public function check_answer($login_answer,$login_name){
$mysql=new Mysqli_stmt_h();//新建一个数据库操作类对象
$sql="select admin_answer from admin_question_data where
admin_name='".$login_name."'";//构造 SQL 语句
$arr=$mysql->oper_query($sql);//去数据库中的问题
$mysql->conn_close();//关闭数据库连接
if($login_answer==$arr[0][0]){
return 1;//答案正确返回 1
}else{
return 0;//答案错误返回 0
}
}
以上的两个函数都位于 的 login_service 类中,所以
调用时通过该类的对象即可进行调用。
以上即为管理员登陆的代码实现过程和介绍。
管理层-----管理员登入功能图示
登入页面图示见图 ,这里选择登陆模式为“管理员”。
图
问题验证页面见图 ,系统显示的问题,需要管理员进行回答。
图
以上即为管理员登陆过程的图示,这里设计双重登入校验是考虑到系统的安全性。
管理层-----管理员操作功能三层模式设计
首先,对于管理员来说,他具有最高权限,既能操作数据库中的数据,也可以操
作 XML 文件中的数据,那么底层的数据层具有数据库中存储的数据,也有 XML 文
件中存储的数据需要管理员操作。其实这里就是涉及到菜单中菜品信息的更新,还有
就是有关于订单的处理。那么在视图层涉及的视图页面也就是菜单更新界面、订单处
理界面、日订单数据查看界面(这里的日订单数据是模拟的数据,通过作图工具表示
的条形图)。对于业务层,即处理层包含的业务处理有订单数据处理以及菜品更新的
处理页面和函数。设计图见(图 )。
图
管理层-----管理员操作功能实现
下下下下下下下MVC下下下
下下下
database
下下下
下下下
Restaurant_admin_operation_pro
Manage menu
Restaurant_admin_manage_me
hp
su
bm
it
Restaurant_admin_me
Restaurant_admin_
add
update
call
Restaurant_admin_operation_ser
call
operation
Check Submit
su
bm
it
Restaurant_check_user_order
Restaurant_check_user_order
call
call
xml下下
Restaurant_earning_statics.
php
Check statics
Restaurant_days_statics_painting.
php
call
就本系统来讲,管理员操作主要为订单查看以及菜品更新,这里也就只这两项功
能的实现进行详细介绍。
点击查看订单,页面跳转到 ,这个页面会给出订
单信息,点击处理即可处理订单信息。下面给出实现代码:
$i=0;//调用 get_submit_order_dishes 函数操作 XML 文件
$arr=$check_order_service->get_submit_order_dishes();//获取当天的未处理订餐信息
if(!empty($arr)){//判断当天订餐信息是否为空
foreach ($arr as $key_id=>$val){//foreach 循环显示订餐信息
echo"<div class='record'>";//每一个订餐信息使用 DIV 包围
foreach ($val as $key=>$val){
if(is_string($key)){
echo"菜名:".$key."---份数".$val."<br>";
}else if(is_int($key)){
if($i==0)
echo "地址:";
else
if($i==1)
echo"价格:";
else
if($i==2)
echo"时间:";
else
if($i==3)
echo"电话:";
echo"$val<br>";
$i++;
}
}//不为空,即显示出订单信息
echo"<a href='
</a>";//处理超链接,将订单处理请求发送至
echo"</div>";
}
}else{
echo"<div class='record'>";
echo"暂无订餐记录!";
echo"</div>";//为空返回订餐信息为空
}
订餐处理实现代码如下, 中的代码主要
用于接收订单处理消息,根据该消息,选取相应的函数处理:
$check_order_service=new check_order_sevice();
if($_GET['order_id']){
$order_id=$_GET['order_id'];
$check_order_service->deal_submit_order_dishes($order_id);
//调用 deal_submit_order_dishes 函数来处理订单
header("location:");//并跳转回原页面继续处理
}
get_submit_order_dishes()代码如下:
public function get_submit_order_dishes(){
date_default_timezone_set("Asia/Shanghai");
$time=date("Y-n-j");//获取当天的日期
$xml_path="documents_xml/";
$xmldoc=new DOMDocument();
$xmldoc->load($xml_path);//加载 XML 文件
$arr=array();//初始化数组,用于订单的回馈
$order_dates=$xmldoc->getElementsByTagName("order_time");//获取日期子节点
for($i=0;$i<$order_dates->length;$i++){
if($order_dates->item($i)->attributes->getNamedItem('time')->nodeValue==$time){
$order_ids=$order_dates->item($i)->childNodes;//遍历日期子节点,返回当天
日期节点信息下的子节点
for($j=0;$j<$order_ids->length;$j++){//遍历子节点信息
if($order_ids->item($j)->lastChild->nodeValue=="on"){
$order_dishes=$order_ids->item($j)->childNodes;
for($n=0;$n<$order_dishes->length-1;$n++){
if($order_dishes->item($n)->nodeName=="order_name"){
$arr[$order_ids->item($j)->attributes->getNamedItem("id")
->nodeValue][$order_dishes->item($n)->attributes->
getNamedItem("name")->nodeValue]=$order_dishes->
item($n)->firstChild->nodeValue;
}else
$arr[$order_ids->item($j)->attributes->getNamedItem("id")->
nodeValue][$n]=$order_dishes->item($n)->nodeValue;
}
}
}//那些未处理的订单才会写入数组中,即 state 节点为 off 的子节点
}
}
return $arr;//返回数组,即返回取到的订单信息
}
以上的两个函数都位于 的 check_order
_sevice 类中,所以调用时通过该类的对象即可进行调用。
点击修改菜品,进入 页面,这里有提供添加
菜品信息和修改菜品信息的功能选项。
当点击添加菜品信息时,进入添加菜品信息页面,并填写相应的菜品信息,提交
至 中进行处理,主要是完整性和合法性的处
理,再调用相应的处理函数对接收的数据进行处理。以下是相关处理代码:
if(!empty($_POST['dishes_name'])&&!empty($_POST['dishes_value'])&&!empty($_POS
T['dishes_kind'])&&!empty($_FILES['dishes_path']['name'])){//数据进行完整性校验
$dishes_name=$_POST['dishes_name'];
$dishes_value=$_POST['dishes_value'];
$dishes_kind=$_POST['dishes_kind'];
$file_name=$_FILES['dishes_path']['name'];
$file_path=$_FILES['dishes_path']['tmp_name'];
$path="dishes_image/".$file_name;
$res=$admin_opration->add_menu($file_name, $file_path);//图片文件上传
if($res){//成功返回 true,不成功返回 false
$sql="insert into Dishes(dishes_name,dishes_value,dishes_kind,dishes_path)
values('".$dishes_name."',".$dishes_value.",'".$dishes_kind."','".$path."')";
if($admin_opration->sql_update_menu($sql)==1){//上传成功,返回提示
header("location:
}else{//写数据库出错,提示上传不成功
header("location:
}
}else{//写文件出错,提示上传不成功
header("location:
}
}else{//数据不完整,返回错误信息
header("location:
}
这里调用了两个函数,分别为 add_menu 和 sql_update_menu 这两个函数,前一
个为将菜品的图片信息写入相应的文件,后者则将菜品信息写入数据库中,这两个函
数都位于 文件中,都是
admin_operation_service 类中的函数,通过对象调用即可。具体代码如下:
add_menu($file_name,$file_path)函数代码如下:
public function add_menu($file_name,$file_path){
$path="dishes_image/".$file_name;//构造文件存储路径
$path=iconv("utf-8","gb2312",$path);//进行 utf-8 中文转码
if(is_uploaded_file($file_path)){//判断上传文件是否存在
if(move_uploaded_file($file_path,$path))//进行文件上传
return 1;
else
return 0;
}
}
sql_update_menu($sql)函数代码如下:
public function sql_update_menu($sql){
$mysql=new Mysqli_stmt_h();
$res=$mysql->oper_data($sql);//调用数据库处理类中的函数进行处理
$mysql->conn_close();
return $res;//返回处理结果,正确将返回 1
}
当点击修改菜品信息时,会在 页面分页显示
所有的菜品信息,管理员查看这些菜品信息,并选择修改项。同时于每一个菜品左下
角含有删除按钮,可以删除相应的菜品信息。所提交的删除或修改信息都会提交到
这个处理页面,再调用 Restaurant_admin_
中的函数进行处理。具体的实现代码如下:
菜品信息更新处理代码:
if(!empty($_POST['dishes_update'])){//接收的数据来自菜品信息更新请求
$dishes_id=$_POST['dishes_id'];
$dishes_name=$_POST['dishes_name'];
$dishes_value=$_POST['dishes_value'];
$dishes_kind=$_POST['dishes_kind'];
$dishes_path=$_POST['dishes_path'];//接收更新的数据
$sql="update dishes set dishes_name='".$dishes_name."',dishes_value=".$dishes
_value.",dishes_kind='".$dishes_kind."',dishes_path='".$dishes_path."' where dishes
_id='".$dishes_id."'";//构造 SQL 跟新语句
$admin_opration->sql_update_menu($sql);//调用函数进行处理
$pagenow=$_GET['pagenow'];//得到所更新的页面,返回至该页面
header("location:
exit();
}
菜品信息删除处理代码:
if(!empty($_POST['pagenow'])){//为了区别开更新数据,这里判断用 POST 提交的页数
$dishes_id=$_POST['dishes_id'];
$pagenow=$_POST['pagenow'];
$dishes_path=$_POST['dishes_path'];//接收相应的删除信息
$sql="delete from dishes where dishes_id=$dishes_id";//构造 SQL 删除语句
$dishes_path=iconv("utf-8","gb2312",$dishes_path);//进行转码声明
if(unlink($dishes_path))//首先删除文件中的菜品图片
{
$admin_opration->sql_update_menu($sql);//调用函数进行数据库删除操作
header("location:
}//删除完成后,同时跳转回相应的页面
exit();
}
以上的菜品添加功能,菜品更新功能,菜品删除功能都涉及到了对文件和数据库
的操作,所以所调用的一些函数也进行了复用,如 sql_update_menu 函数,这个函数
主要是对数据库的更新操作,所以都调用这个函数执行。
以上即为管理员登陆的代码实现过程和介绍。
管理层-----管理员操作功能图示
点击修改菜品->修改菜品信息图示,见图 。
图
将地三鲜价格改为 15,点击修改后见图 .
图
当点击地三鲜左下角的删除键,见图 。
图
此时地三鲜已不见,菜品信息会相应的顶替地三鲜原来的位置,继续显示,此时再点
击添加菜品信息,将地三鲜加回菜品信息中,见图 。
图
点击提交,添加成功,将显示添加成功信息,见图 。
图
再次查看菜品信息,可以看到地三鲜菜品又回到菜品信息列表中,见图 。
图
网上订餐系统管理层功能总结
经过前期的设计规划以及后期的实施,网上订餐系统管理层功能基本得到了实现,
经过以上详细的介绍,相信你已经对本系统的管理层的功能有了一个全面而深入的了
解,对这些功能具体的实现方案也有了清晰的认识。通过一系列的测试,本系统管理
层各类功能运行良好,符合最初的设计需求。
第四章:网上订餐系统用户层功能设计与实现
系统用户层简述
一个系统推出,其最主要的需求是基于用户使用。用户使用该系统来完成一些系
统所支持的操作,达到系统设计初的目的。对于系统设计初来说,用户层的需求分析
与系统结构设计又是十分重要的。因为一个好的系统,需要为系统的使用者考虑到各
方面的问题和功能需求,故如何做好用户层的设计,以及如何更好的实现用户层而不
降低其可用性,是系统用户层不可回避的课题。下面,就本系统的用户层进行介绍。
网上订餐系统用户层功能设计与实现
用户层-----用户登入、注册功能三层模式设计
对于一个网站,最为基础是要为用户提供注册和登入功能,这两个基本的功能是
构成用户信息采集和登入的基础。那么对于登入和注册,在界面层需要提供登入界面
和注册界面,这是基本的两个界面;由于数据都保存在数据库中,所以对于注册和登
入都是和数据库进行交互的,所以在数据层仅仅有数据库提供数据服务;这两个功能
的实现主要在于处理层中的数据处理界面和函数,这里设计了两个类来提供函数服务,
分别为 类和 类,这里面包含着处理登入和注册的函数,即
对于数据库数据的读写操作。同时根据 MVC 模式,依然跟随着两个处理过程界面
和 ,这两个界面提供数据
的处理,完整性和合法性的处理。设计图见(图 )。
用户层-----用户登入、注册功能实现
用户的登入和注册功能,作为本系统的最为基础的两项功能而存在。首先,对于
注册功能来说,用户点击网上注册,进入注册界面,填写完注册信息后,点击提交按
钮,用户所提交数据将发送到 页面进行合法性和完整
性校验,再调用 页面中的函数进行处理。当注册成功
后会跳转至登入页面。用户在登入页面输入登入名和密码,选择用户模式登入,提交
数据后将发送至 中进行处理,并将处理后的数据交由
页面的函数处理,登入成功,将进入用户订餐界面。
图
下面就注册功能实现的具体代码进行分析,其代码如下:
if(!empty($_POST['user_name'])&&!empty($_POST['user_telephone'])&&!empty($_POS
T['user_email'])&&!empty($_POST['user_address'])&&!empty($_POST['user_password'])
&&!empty($_POST['password'])&&!empty($_POST['checkcode'])){//判断数据完整性
$user_name=$_POST['user_name'];
$user_telephone=$_POST['user_telephone'];
$user_email=$_POST['user_email'];
$user_address=$_POST['user_address'];
$user_password=$_POST['user_password'];
$password=$_POST['password'];
下下下下下下、下下mvc下下下
database
下下下
下下下
下下下
Login
Restaurant_login_process.
php
su
bm
it
Restaurant_login_service.
php
call
operation
legal
illegal
Restaurant_register_pageone.
php
register
Retaurant_register_process.
php
su
bm
it
Restaurant_register_server.
php
Legal\call
illegal
call
Register complete
$checkcode=$_POST['checkcode'];//接收所提交的数据
$arr=$register_service->get_user_name();//获取所有用户名
foreach($arr as $val){
foreach ($val as $array_name)
if($user_name==$array_name){//比较检验注册用户名是否与已有冲突
header("location:
exit();//若有,返回提示用户,修改注册名
}
}
if($user_password!=$password){
header("location:
exit();
}else{
$user_password=md5($user_password);
}//检验注册时两次输入密码是否一致
if($checkcode!=$_SESSION['checkline']){
header("location:
exit();
}//检验验证码是否正确
$sql="insert into user_infor_data(user_name,user_password,user_telephone,
user_email,user_address) values('".$user_name."','".$user_password."','".$user_
telephone."','".$user_email."','".$user_address."')";//构造 SQL 语句
$res=$register_service->register_add($sql);//调用函数执行 SQL 语句
if($res){
header("location:
exit();//注册成功,跳转至登入界面
}else{
header("location:
exit();//注册失败,返回错误信息
}
}else{
header("location:
exit();//信息不完整,返回错误信息
}
以上代码中涉及到 页面的两个函数,也是 register
_service 类中两个函数,分别为 register_add($sql)和 get_user_name()。前一个函数用于
添加注册信息至数据库中,第二个函数用于取数据库中所有的用户名信息。
函数 register_add($sql)代码如下:
public function register_add($sql){
$mysql=new Mysqli_stmt_h();//创建数据库处理类对象
$res=$mysql->oper_data($sql);//调用数据库处理函数,处理 SQL 语句
$mysql->conn_close();//关闭连接
return $res;//返回处理结果,处理成功返回 1
}
函数 get_user_name()代码如下:
public function get_user_name(){
$mysql=new Mysqli_stmt_h();//创建数据库处理类对象
$sql="select user_name from user_infor_data";//构造 SQL 语句
$arr=$mysql->oper_query($sql);//调用数据库处理函数,处理 SQL 语句
$mysql->conn_close();//关闭连接
return $arr;//将查询数据返回
}
接着就用户登入功能实现的具体代码进行分析,由于用户登入代码和管理员登入代码
有复用的地方,这里仅给出用户登入代码的核心部分,其代码如下:
if(!empty($_POST['login_model'])){
$login_modle=$_POST['login_model'];
}//接收登入模式
$res=$login_service->check_password($login_name,$password,$login_modle);
if($res){//检验登入密码无误
if($login_modle=="user"){//用户登入
$_SESSION['user_name']=$login_name;//用户名写入 SESSION 文件中
$user_id=$login_service->get_user_id($login_name);
$_SESSION['user_id']=$user_id[0][0];//将获取的 id 写入 SESSION 文件中
$_SESSION['user_order_num']=3;//将提交订单的次数写入 SESSION 文件
$order_arr=$login_service->receive_order_dishes($user_id[0][0]);
if(!empty($order_arr))//获取用户购物篮信息,若有,则写入 SESSION 中
$_SESSION['order_array']=$order_arr;
header("location:");
exit();//跳转至用户订餐界面
}
}
以上代码涉及到较多的函数调用,调用的函数均来
文件中,即来自 login_service 类中的函数,通过类实例化对象进行调用,来处理和获
取数据。这里主要对 receive_order_dishes 函数进行分析,因为这个函数的功能是从
XML 文件中读取用户的购物篮信息。
函数 receive_order_dishes($userid)代码如下:
public function receive_order_dishes($userid){
$xml=new DOMDocument();
$filename="documents_xml/";
$xml->load($filename);//加载 XML 文件
$arr=array();//初始化数组
$user_order_root=$xml->getElementsByTagName("user_id");
for($i=0;$i<$user_order_root->length;$i++){//遍历名为 user_id 的子节点
if($user_order_root->item($i)->attributes->getNamedItem('id')->nodeValue
==strval($userid)){//判断 XML 文件中是否存在登入用户的购物篮信息
$locate_root=$user_order_root->item($i);
for($i=0;$i<$locate_root->childNodes->length;$i++){
$dishes_name=$locate_root->childNodes->item($i)->
attributes->getNamedItem('name')->nodeValue;
$dishes_num=$locate_root->childNodes->item($i)->
firstChild->nodeValue;
$arr[$dishes_name]=(int)$dishes_num;
}//若有,循环取出信息至数组中
break;//退出子节点的遍历
}
}
return $arr;//返回数组信息
}
以上即为用户登入和注册功能的实现过程和介绍。
用户层-----用户登入、注册功能图示
点击网上注册,进入注册页面,填写注册信息,点击用户注册,注册成功进入登
入界面。具体请见图 、图 。
图
图
用户登入,点击网页登入,填写登入信息,选择普通用户登入模式,点击用户登
入,即进入用户订餐界面。具体见图 、图 .
图
图
用户小明登入,并取出了小明以往的购物篮信息。
用户层-----用户操作功能三层模式设计
用户的操作主要是订餐操作,用户点击订单,所点的餐品将显示在左边购物篮中。
同时,最后用户需要点击确认订单,用以修改订餐信息以及最后修改订餐的菜品信息,
包括修改份数和删除不需要的菜品,然后点击订餐提交到 XML 文件中供管理员查看
并处理。最后,在用户退出时,若购物篮中还有菜品,即会在退出时保存到 XML 文
件中,以供用户下次登入时显示出来。同时,提供给用户查看以往订餐的记录,当点
击查看以往订餐记录时,如果有订餐记录的话,会给出以往订餐记录时间的下拉列表,
点击选择时间进行查看。所以,介于以上的些许功能,这里提供了两个三层模式设计,
分别是订餐功能和查看订餐记录和退出的 MVC 模式设计图。(见图 和 )
图
上图为点击订餐操作以及点击确认订单操作后提交订单的操作,这里包括订单信
息的更新、菜品的删除等操作,当有非法数据或操作产生是,会返回错误信息。
下下下下下下MVC下下下
下下下
下下下
下下下
order
operation
check
su
bm
it
illegal
call
Order complete
delete Delete okupdate update ok
xml下下
图
上图为查看订单记录及退出操作动作的 MVC 模式设计图,退出操作和查看订单
记录操作都是与 XML 文件交互的,数据层就仅有 XML 文件。
下下下
下下下
下下下
下下下下下下下下下下下下下下下
call
xml下下
Operation
call
submit
Restaurnt_login_service,php
quit
operation
Restaurant_main_page,php
用户层-----用户操作功能实现
用户操作功能包括以下几大类,一是用户点击订餐按钮,订购菜品;二是用户查
看订购的餐品;三是查看用户以往的订餐记录;四是退出系统。下面进行一一介绍其
实现过程。
对于第一点,当用户点击订餐时,订餐请求发送至
页面进行处理,处理完成后会返回到提交该请求的相应页面。下面给出相应的实现代
码。
$str=$_SERVER['HTTP_REFERER'];//全局变量 SERVER 中取出提交数据的页面
$start=strpos($str,'R');
$end=strrpos($str,'.');
$length=$end-$start+1;
$back=substr($str, $start,$length);
$back=$back."php";//给出返回的页面
if(!empty($_SESSION['user_name'])){//看用户点击订餐时是否登入
$order_num=$_POST['order_number'];
$order_num=(int)$order_num;
$order_dishes_name=$_POST['order_dishes_name'];//接收点餐的份数和菜品名称
if(empty($_SESSION['order_array']))//查看是否在 SESSION 中存在点餐信息
{
$arr=array();
$arr[$order_dishes_name]=$order_num;
$_SESSION['order_array']=$arr;//没有,则从新创建
}else{
$arr=$_SESSION['order_array'];//有,则直接取出数据
foreach ($arr as $key=>$val){
if($key==$order_dishes_name){//遍历数据,查看是否已存在该餐点信息
$arr[$key]+=$order_num;//存在,则响应相关餐点份数加一
$flag=true; //标记给餐点信息已存在
}
}
if(!$flag){//若为存在,作为新的一条记录写入数据
$arr[$order_dishes_name]=$order_num;
}
$_SESSION['order_array']=$arr;//最后把数据写回 SESSION 中
}
header("location:".$back);//返回订餐页
exit();
}else{
header("location:".$back."?order=1");//为登入,返回提示信息
exit();
}
对于第二点,用户点击确认订单,用户可以看到订购的菜品信息,包括送餐电话,
送餐地址,送餐时间,菜品价格等内容。同时用户也可以进行菜品的修改,删除、改
变份数等操作。最后点击提交,提交订单。这些动作消息都是发送到相应的处理页面
来进行处理,即上述的 页面,再调用 Restaurant_order
页面的函数进行数据写文件和写数据库等操作。下面是具体的代码实现
过程。
if(!empty($_GET['d_d_name'])){//对于删除订单中菜品信息处理
$d_d_name=$_GET['d_d_name'];
unset($_SESSION['order_array'][$d_d_name]);//删除 SESSION 文件中的菜品信息
header("location:".$back);
exit();
}
if(!empty($_POST['update_num'])){//对于更新菜品数量处理
$update_num=(int)$_POST['update_num'];
$update_dish_name=$_POST['update_dishes_name'];
$_SESSION['order_array'][$update_dish_name]=$update_num;//改变菜品的数量
header("location:".$back);
exit();
}
if(empty($_POST['notice'])){//是否选中了订餐提示
header("location:".$back."?error=3");
exit();
}
if(!empty($_SESSION['order_array'])){//订餐信息是否为空
$flag=false;
if(!empty($_POST['address'])&&!empty($_POST['time'])&&!empty
($_POST['telephone'])){//提交的送餐信息不完整
if($_SESSION['user_order_num']!=0){//查看订餐提交次数是否达上限
if(empty($_SESSION['min'])){
$min=(int)date("i");
$_SESSION['min']=$min;
}else{
if(date("i")-$_SESSION['min']>=10){
header("location:
exit();
}//判断信息提交的时间是否在十分钟内完成,超过时间,不予接收
}
$user_address=$_POST['address'];
if(!empty($_POST['change_address'])){
$user_name=$_SESSION['user_name'];
$order_service->update_address($user_address, $user_name);
$flag=true;
}//送餐地址不是默认,是否需要保存更改地址
$user_telephone=$_POST['telephone'];
if(!empty($_POST['change_telephone'])){
$user_name=$_SESSION['user_name'];
$order_service->update_telephone($user_telephone, $user_name);
$flag=true;
}//送餐电话不是默认,是否需要保存更改电话
$price=$_POST['price'];
$time=$_POST['time'];
$order_array=$_SESSION['order_array'];
$user_id=$_SESSION['user_id'];//接受订餐信息
$order_service->submit_order_dishes($order_array,$user_id,$user_
address,$price,$time,$user_telephone);//提交订餐信息
$_SESSION['user_order_num']-=1;//d 订餐提交次数减一
if(!$flag)
{
header("location:".$back."?success=1");
exit();
}else{
header("location:".$back."?success=2");
exit();
} //处理完成,返回信息提交成功信息
}else{//订餐提交次数超过三次,不可再进行提交
header("location:".$back."?error=4");
exit();
}
}else{//提交的送餐信息不完整,返回错误信息
header("location:".$back."?error=1");
exit();
}
}else{//没有订餐,提交提示信息,没有订餐,不能提交
header("location:".$back."?error=2");
exit();
}
下面重点就 submit_order_dishes 函数进行介绍,这个函数用于向 XML 文件中写
入订餐的信息。位于 文件中,且是 order_service 类的函
数,通过该类的对象进行调用。
submit_order_dishes($order_array,$user_id,$user_address,$price,$time,$user_telephone)
函数代码如下:
public function submit_order_dishes($order_array,$user_id,$user_address,$price,$time,
$user_telephone){
$xml_path="documents_xml/";
$xmldoc=new DOMDocument();
$xmldoc->load($xml_path);//加载 XML 文件
$t_flag=false;
$u_flag=false;
$root=$xmldoc->getElementsByTagName("submit_order")->item(0);
$submit_order_root=$xmldoc->getElementsByTagName("submit_order")
->item(0)->childNodes;//获取时间子节点
for($i=0;$i<$submit_order_root->length;$i++){
if($submit_order_root->item($i)->attributes->getNamedItem("time")->
nodeValue== date("Y-n-j")){//遍历时间子节点,若有当天的时间节点,定位之
$order_time=$submit_order_root->item($i);
$t_flag=true;//定位到当天时间子节点标准位
break;
}
}
if(!$t_flag){//若没有,则创建新的时间子节点
$order_time=$xmldoc->createElement("order_time");
$order_time->setAttribute("time",date("Y-n-j"));
$root->appendChild($order_time);
}
$order_id=$order_time->childNodes;//时间子节点下属子节点
for($i=0;$i<$order_id->length;$i++){
if($order_id->item($i)->attributes->getNamedItem("id")->
nodeValue==strval($user_id)){//遍历下属子节点,是否存在该用户
$user_order_id=$order_id->item($i);
$u_flag=true;//有,定位到该用户 ID 节点下,并改写标至位
break;
}
}
$dish_address=$xmldoc->createElement("address");
$dish_address->nodeValue=$user_address;
$dish_price=$xmldoc->createElement("price");
$dish_price->nodeValue=$price;
$dish_time=$xmldoc->createElement("time");
$dish_time->nodeValue=$time;
$dish_telephone=$xmldoc->createElement("telephone");
$dish_telephone->nodeValue=$user_telephone;
$dish_state=$xmldoc->createElement("state");
$dish_state->nodeValue="on";//创建各类订餐信息节点
if(!$u_flag){//若不存在给用户 ID 节点,创建新的用户 ID 节点
$user_order_id=$xmldoc->createElement("order_id");
$user_order_id->setAttribute("id", strval($user_id));
$order_time->appendChild($user_order_id);
foreach($order_array as $key=>$val){
$dish_name=$xmldoc->createElement("order_name");
$dish_name->setAttribute("name", $key);
$dish_num=$xmldoc->createElement("order_num");
$dish_num->nodeValue=$val;
$dish_name->appendChild($dish_num);
$user_order_id->appendChild($dish_name);
}//写入用户餐点信息
}else{
while($user_order_id->childNodes->item(0)&&$user_order_id->removeChild
($user_order_id->childNodes->item(0)));//若存在,则先删除原有用户信息
foreach ($order_array as $key=>$val){
$dish_name=$xmldoc->createElement("order_name");
$dish_name->setAttribute("name", $key);
$dish_num=$xmldoc->createElement("order_num");
$dish_num->nodeValue=$val;
$dish_name->appendChild($dish_num);
$user_order_id->appendChild($dish_name);
}//在循环写入用户原有菜品信息
}
$user_order_id->appendChild($dish_address);
$user_order_id->appendChild($dish_price);
$user_order_id->appendChild($dish_time);
$user_order_id->appendChild($dish_telephone);
$user_order_id->appendChild($dish_state);//添加订餐信息节点
$xmldoc->save($xml_path);//写回 XML 文件
}
对于第三、第四点,用户点击订餐记录,通过下拉的时间列表,来选择以往的订餐记
录进行查看。对于退出,点击退出登录,跳转到 页面进
行退出处理。下面给出具体的实现代码和过程。
$user_id=$_SESSION['user_id'];
$arr=$order_service->get_submit_order_date($user_id);//用户 ID 取出订餐记录日期
if(!empty($arr)){//若有,则遍历出订餐记录日期,以下拉列表的方式给出
echo"<form action='' method='post'>";
echo "您的订餐日期的记录有,请选择:";echo"<select name='time'>";
foreach ($arr as $key=>$val){
echo"<option value='$key'>$val</option>";
}
echo"</select>";
echo"<input type='submit' value='查询'/>";
echo"<form>";//查询请求提交到本页面执行
}else{//若没有订餐记录,则显示无
echo "无订餐记录!";
}
if(!empty($_POST['time'])){//若有订餐记录查看请求
$time=$_POST['time'];//接收查看订单的时间
$user_id=$_SESSION['user_id'];//用户 ID
$arr=$order_service->get_submit_order_dishes($time, $user_id);//给出订餐记录
echo"<div class='record'>";
$i=0;
foreach ($arr as $key=>$val){
if(is_string($key)){
echo"菜名:".$key."---份数".$val."<br>";
}else if(is_int($key)){
if($i==0)
echo "地址:";
else
if($i==1)
echo"价格:";
else
if($i==2)
echo"时间:";
else
if($i==3)
echo"电话:";
echo"$val<br>";
$i++;
}
}//遍历给出订餐记录
echo"</div>";
}
以上有两个函数,一个是 get_submit_order_date 函数,用于取出用户可能存在的
订餐记录的日期;第二个是 get_submit_order_dishes 函数,给出用户的在某个日期下
的订餐记录信息。两个函数都位于 页面中,即 order
_service 类中的函数,通过类对象调用即可。
get_submit_order_date($user_id)函数如下:
public function get_submit_order_date($user_id){
$xml_path="documents_xml/";
$xmldoc=new DOMDocument();
$xmldoc->load($xml_path);//加载 XML 文件
$arr=array();
$order_dates=$xmldoc->getElementsByTagName("order_time");
for($i=0;$i<$order_dates->length;$i++){
if($order_dates->item($i)->attributes->getNamedItem("time")->nodeValue!
=date("Y-n-j")){//取出日期不等于当天的所有日期节点的子节点
$order_ids=$order_dates->item($i)->childNodes;
for($j=0;$j<$order_ids->length;$j++){
if($order_ids->item($j)->attributes->getNamedItem("id")
->nodeValue==strval($user_id)){
$arr[$order_dates->item($i)->attributes->getNamedItem
("time")->nodeValue]=$order_dates->item($i)->attributes
->getNamedItem("time")->nodeValue;
}
}//遍历出存在用户 ID 的日期子节点,存储 time 属性值
}
}
return $arr;//返回日期信息数组
}
get_submit_order_dishes($time, $user_id)函数如下:
public function get_submit_order_dishes($time,$user_id){
$xml_path="documents_xml/";
$xmldoc=new DOMDocument();
$xmldoc->load($xml_path);
$arr=array();
$order_dates=$xmldoc->getElementsByTagName("order_time");//日期下的子节点
for($i=0;$i<$order_dates->length;$i++){
if($order_dates->item($i)->attributes->getNamedItem('time')->nodeValue
==$time){//遍历日期子节点,若等于所提交的查找日期
$order_ids=$order_dates->item($i)->childNodes;//此日期下的子节点
for($j=0;$j<$order_ids->length;$j++){
if($order_ids->item($j)->attributes->getNamedItem('id')->
nodeValue==$user_id){//此 ID 用户下的订餐信息
$order_dishes=$order_ids->item($j)->childNodes;
for($n=0;$n<$order_dishes->length-1;$n++){
if($order_dishes->item($n)->nodeName==
"order_name"){
$arr[$order_dishes->item($n)->attributes
->getNamedItem("name")->nodeValue]=
$order_dishes->item($n)->firstChild
->nodeValue;
}else
$arr[$n]=$order_dishes->item($n)->nodeValue;
}//遍历获取订餐信息
}
}
}
}
return $arr;//返回该信息
}
点击退出时,实现代码如下:
$user_id=$_SESSION['user_id'];
$login_service->save_order_dishes($user_id);//保存购物篮信息
unset($_SESSION['user_id']);
unset($_SESSION['user_name']);
unset($_SESSION['user_order_num']);//清空 SESSION 信息
header("location:");
exit();
这里的函数 save_order_dishes($user_id)函数在 login_service 类中,主要为将购物
篮信息写回到 XML 文件中去。代码如下:
public function save_order_dishes($userid){
$xml=new DOMDocument();
$filename="documents_xml/";
$xml->load($filename);
$order_root=$xml->getElementsByTagName("order_dishes")->item(0);
$flag=false;
$user_order_root=$xml->getElementsByTagName("user_id");
for($i=0;$i<$user_order_root->length;$i++){
if($user_order_root->item($i)->attributes->getNamedItem('id')->nodeValue
==strval($userid)){//首先判断 XML 文件中是否已存在该用户信息
$locate_root=$user_order_root->item($i);
$flag=true;//存在,标准位为 TRUE
break;
}
}
if(!$flag){
$user_id=$xml->createElement("user_id");
$user_id->setAttribute("id",strval($userid));
$arr=$_SESSION['order_array'];//不存在该用户节点信息,创建新节点
foreach ($arr as $key=>$val)
{
$dishes_name=$xml->createElement("dishes_name");
$dishes_name->setAttribute("name",$key);
$dishes_num=$xml->createElement("dishes_num",$val);
$dishes_name->appendChild($dishes_num);
$user_id->appendChild($dishes_name);
}//循环写入用户购物篮信息
$order_root->appendChild($user_id);//添加此节点
}else{
$user_id=$locate_root;
$Child=$user_id->childNodes;//如有,先删除该节点原有信息
while($Child->item(0)&&$user_id->removeChild($Child->item(0)));
$arr=$_SESSION['order_array'];
foreach ($arr as $key=>$val)
{
$dishes_name=$xml->createElement("dishes_name");
$dishes_name->setAttribute("name",$key);
$dishes_num=$xml->createElement("dishes_num",$val);
$dishes_name->appendChild($dishes_num);
$user_id->appendChild($dishes_name);
}//循环遍历,写入购物篮信息
}
$xml->save($filename);//保存 XML 文件
}
以上即为用户操作层的实现过程和代码的介绍。
用户层-----用户操作功能图示
用户点击订餐,并在购物篮显示。详见图 、。
图
小智用户点击订餐,订购无锡排骨后,在购物篮子显示出来。
图
点击确认订单后,进入订单确认页面,点击提交,即可提交订单,并返还提示信
息,见图 。
图
如要查看订餐记录,点击订餐记录即可选择相应的时间进行记录查看,详见图
、。
图
图
网上订餐系统用户层功能总结
经过上述的用户层功能的需求分析和代码实现,用户层的基本的一些功能得到了
很好的实现,每个功能都实现了前期需求分析设计所要达到目的。各功能模块也符合
设计初的执行效果,总体用户层经代码实现后达到了最初的设计需求和目的。通过以
上详细的介绍,相信您已经对用户层有了一个详细的认识和了解。
第五章:网上订餐系统项目总结
通过此订餐系统项目,对于一个网页系统的构建有了深入的学习,也对 MVC 的
开发模式有了深入的理解,同时对使用 PHP 脚本构建一个项目的步骤有了深入的探
索。当然,在开发和代码编写阶段也在不断的对项目的需求和结构进行着调整和修改,
所以对于先期的需求分析和系统结构设计对于一个项目的后续实施来说是非常的重
要,有了前期好的规划,才能使得后期更加的顺利。同时,经过测试,虽然此项目的
各项功能得到了实现,但综合来说,其系统的健壮性、完整性方面还是比较的欠缺,
系统的运行还是比较的缓慢,没有引入模板开发技术、AJAX 页面回掉技术,当然这
些也是多用于大型、高访问量的网站需要考虑的,但这对于提高项目的反应速度会有
很好的帮助。总之,项目需要提供和修改的地方还有很多,需要进一步加强的地方也
有很多,只有不断的进行完善和测试,才能最终提供给用户一个满意的系统。
参考文献:
[1] Michael kofler. MySQL 5 权威指南[M]. 北京: 人民邮电出版社, 2006.
[2] 潘凯华, 邹天思. PHP 开发实战宝典[M]. 北京: 清华大学出版社, 2010.
[3] Gilmore. PHP 与 MySQL5 程序设计. 人民邮电出版社,2007 年 4 月.
[4] 卜佳旭. 基于 MVC 模式企业信息管理系统设计与实现[D]. 2008.
[5] Dafydd Stuttard Marcus Pinto.黑客攻防技术宝典 WEB 实战篇(第二版). 人民邮
电出版社,2012 年 7 月.
[6] 许莉. HTML 与 CSS 前台页面设计 . 中国水利水电出版社,2011 年.
附录:
在附录中给出 代码分析,即数据库操作函数:
此文件中的代码是对于底层数据库操作的代码,我们将其封装成了一个类,当要
使用这个类时,使用 require_once 将文件引入,然后创建类对象,调用里面的函数即
可,代码如下所示。
class Mysqli_stmt_h{
private $mysqli;
private $mysqli_stmt;
private static $host="localhost";
private static $usn="root";
private static $psw="root";
private static $db="Restaurant_data";
function __construct(){
$this->mysqli=new MySQLi(self::$host,self::$usn,self::$psw,self::$db);
if($this->mysqli->connect_error){
die("连接失败".$this->mysqli->connect_error);
}
$this->mysqli->query("set names utf8");
}
public function oper_data($sql){
$res=$this->mysqli->query($sql) or die($this->mysqli->error);
if(!$res){
return 0;
}else{
if($this->mysqli->affected_rows>0)
return 1;
else
return 2;
}
}
public function oper_query($sql){
$arr=array();
$res=$this->mysqli->query($sql);
$i=0;
while($row=$res->fetch_row())
{
$arr[$i++]=$row;
}
$res->free();
return $arr;
}
public function conn_close(){
$this->mysqli->close();
}
}
这个类提供了四个函数,第一个为从写构造函数,主要为数据库连接的初始化工作,
oper_data($sql)函数主要为进行数据库的更新操作,增加、删除、修改操作。
oper_query($sql)函数主要为进行数据库数据的查询操作,返回一个查询到的数组,
并及时释放数据库查询结果资源。最后一个函数为断开数据库连接的函数,这是连接
数据库后在操作完数据后一个必要的动作。