做个简单练习,题目关于点菜。要求用户注册登录之后,来到点菜页面,点菜页面数据从后台数据库获取后页面渲染出来。用户选择的菜品和数量,会自动计算单个菜品的总价,以及所有选择菜品的最后总价。 客户确认提交后,保存在数据库。 管理员则可以添加一个新的菜品,以及查看所有的订单,点击某一个订单,则可以看到客户选择了具体菜品的数量以及价格。由于上一篇 PHP MySQL 简单链接 已经讲过如何注册将用户信息存入数据库,所以这里将不重复,仅演示用户选择菜品,计算价格,提交存入数据库,以及管理员查看订单列表和订单详情。
先上个动图
看过动图,大概过程如此,接下来就讲讲一步步实现的。
首先设计food 表如下
然后设计 order.php 页面
第一部分引入数据库类,然后调用getFood()方法获得所以菜的数据集。
getFood() 方法
public function getFood(){
$sql = "SELECT * FROM food ";
$result = mysql_query($sql,$this->conn);
return $result;
}
第二部分遍历结果集,然后将每一个菜品的信息渲染出来。
第三部分是两个按钮和最后总价的内容。
order.php 页面渲染结果代码
getFood();
?>
Bootstrap 101 Template
你好,世界!
Price: ¥
Num:
SubTotal:
¥0
Total: ¥0
渲染效果如下
JS 监听select 的变化而更改总价,以及点击按钮提交后台
下面涉及到jQuery,如没有接触,建议前往 w3school - jquery 了解一下,否则下面的知识有可能看不明白。
先看看 order的每一项菜品的结构
客户选择数量,总价发生变化是如何完成这个小功能的。
观察一下 select 部分代码
// 父亲节点
Price: ¥123
// 第1个孩子节点
Num:
// 第2个孩子节点
从上面片段代码结构,父亲节点下有三个子节点。
用户在select 选择数据, 所以我们想办法给它绑定方法。
所以这时候可以功能通过jQuery给select 绑定 一个change()方法
change()方法 定义和用法
当元素的值发生改变时,会发生 change 事件。
该事件仅适用于文本域(text field),以及 textarea 和 select 元素。
change() 函数触发 change 事件,或规定当发生 change 事件时运行的函数。
注释:当用于 select 元素时,change 事件会在选择某个选项时发生。当用于 text field 或 text area 时,该事件会在元素失去焦点时发生。
语法
$(selector).change()
(来源w3school)
这样我们可以通过找到 class为 user-select 下面的 select 标签 绑定change方法。
$('.user-select select').change(function(){
});
接下来我们就要知道用户到底选了那个一个值
$('.user-select select').change(function(){
var num = Number($(this).children('option:selected').val());
});
这里如果用户进行了select的操作,就会触发change() 方法。
$(this)表示当前对象,也就是select, select 下面的 option都是它的子节点,$(this).children('option:selected') 表示找到 孩子节点中选项是 被选择的节点,$(this).children('option:selected').val() 表示找到该节点之后,获取对应的值。 Number() 方法是将获取到的值,是字符串,将其转成int。
如果可以拿到 用户选择的数量,那么接下来是要获取当前的菜品的价格。
再回顾一下这片段代码
// 父亲节点
Price: ¥123
// 第1个孩子节点
Num:
// 第2个孩子节点
我们刚刚已经知道$(this)可以获取到当前对象, 那么如果希望得到当前菜品的价格,可以看到 父类下面的第一个节点的里面的span 的值就是我们所需要的price的值。
$('.user-select select').change(function(){
var num = Number($(this).children('option:selected').val());
var price = Number($(this).parent().children().eq(0).find('span').text());
});
$(this).parent() 是找到当前节点的父类, $(this)是 select, 那么父类就是它外层的div。
$(this).parent().children().eq(0) 表示父类下面的所有孩子节点中的第一个节点,下标从0开始。
$(this).parent().children().eq(0).find('span').text() 表示在第一个孩子节点中找到 span标签 并且获取里面的text值。
同样,需要用到 Number()转 int。
到目前为止,应该懂得如何从当前对象找到父类,然后再去找到对应的子节点。
所以接下来的 要做个简单的计算,并且赋值给SubTotal。
再回顾一下这个结构
我们需要找到subtotal的位置
$('.user-select select').change(function(){
var num = Number($(this).children('option:selected').val());
var price = Number($(this).parent().children().eq(0).find('span').text());
var subTotal = num * price;
$(this).parent().parent().children().eq(3).children().eq(1).text(subTotal);
});
这里找到subTotal 的位置的方法和上面类似,请自行了解。text(subTotal)是将计算得到的值进行赋值。
目前为止,单个菜品的数量变化则会变化对应的subtotal的值。
接下来就是计算所有的总价。
因为每个菜品都会有一个类subtotal, 只需要找到所有的subtotal,进行累计就得到总价。
写一个自定义计算总价的方法 gettotal(),需要用到一个each()方法。
定义和用法
each() 方法规定为每个匹配元素规定运行的函数。
语法
$(selector).each(function(index,element))
(来源w3school)
gettotal()自定义方法
function gettotal(){
var total = 0;
$('.subtotal').each(function(){
total = total + parseInt($(this).text());
});
console.log(total);
return total;
}
因为绑定在class为 subtotal,所以$(this)该对象。
$(this).text()获取到对应的text, 通过parseInt()转 int, 进行累加,最后返回计算结果。
所以在用户select 一个值的时候,里面调用这个gettotal() 方法,就可以更新 total的值。
于是乎,有了这个两个方法,就可以实现了当前页面用户更改值,就可以更新对应的总价。
$('.user-select select').change(function(){
var num = Number($(this).children('option:selected').val());
var price = Number($(this).parent().children().eq(0).find('span').text());
var subTotal = num * price;
$(this).parent().parent().children().eq(3).children().eq(1).text(subTotal);
var total = gettotal();
$('.total').text(total);
});
function gettotal(){
var total = 0;
$('.subtotal').each(function(){
total = total + parseInt($(this).text());
});
console.log(total);
return total;
}
如何获取用户选择的数据呢??
首先我们设计数据库用户到底要存什么数据
guest_order 表
fid 对应food 表的id ,外键
fprice 价格
fnum 客户点的数量
fsubtotal 该菜品的总价
guestname 用户名
order_datetime 客户下单时间
还记order页面底部有两个按钮
我们给confirm 按钮绑定一个点击事件。
定义和用法
当点击元素时,会发生 click 事件。
当鼠标指针停留在元素上方,然后按下并松开鼠标左键时,就会发生一次 click。
click() 方法触发 click 事件,或规定当发生 click 事件时运行的函数。
语法
$(selector).click()
(来源w3school)
按钮 代码
Total: ¥0
给confirm 按钮添加了 class sure,再给这个class 绑定click方法。
$('.sure').click(function(){
});
接下来就要考虑下如何获取数据了,我们可以尝试一下数组。而且可能是二维数组。
不妨多看一遍 order的代码结构
每一个菜品就是在一个div内,并且设置一个class 为item
对应每一个item里面的代码
既然我们要获取全部的菜品的数据,我们是不是可以再用一下上面提到的 each的方法。
$('.sure').click(function(){
var data = new Array();
$('.item').each(function(index){
});
});
点击按钮之后 ,先new一个数组。
然后 再调用熟悉的each 方法,只不过我们这里多了个参数,这里的index表示遍历每一个对象的下标值,下标从0开始。
既然来到这里, 我们可以用上面已经试过的方法获取对应的值
$('.sure').click(function(){
var data = new Array();
$('.item').each(function(index){
console.log("index:" + index);
var foodid = $(this).children().eq(4).find('span').text();
var price = $(this).children().eq(2).children().eq(0).find('span').text();
var subTotal = $(this).children().eq(3).find('span').text();
var num = $(this).children().eq(2).find('select').children('option:selected').val();
});
});
这里我就可以分别每次获取到的菜品的数据。
接下来是怎样存的问题了,这里就需要到二维数组了
因为我们打算计划这样去存
一个数组里面,再存一个数组,里面数组数据分别对应是 菜品id,菜品价格,菜品数量,已经该菜品的总价。
所以获取数据存储到二维数组如下
$('.sure').click(function(){
var data = new Array();
$('.item').each(function(index){
console.log("index:" + index);
var foodid = $(this).children().eq(4).find('span').text();
var price = $(this).children().eq(2).children().eq(0).find('span').text();
var subTotal = $(this).children().eq(3).find('span').text();
var num = $(this).children().eq(2).find('select').children('option:selected').val();
data[index] = new Array();
data[index][0]= foodid;
data[index][1]= price;
data[index][2]= num;
data[index][3]= subTotal;
});
});
index 刚刚已经提到时每一个item的index下标,从0开始,
然后 data[index] = new Array(); 表示当前index下再建一个数组,
data[index][0]= foodid;
data[index][1]= price;
data[index][2]= num;
data[index][3]= subTotal;
表示二维数组下分别存储的信息。
如果你坚持一步步到这里,你大概已经快成功了,你可以起来运动下,喝杯水。
5分钟过后....
最难的部分似乎都搞点了,现在问题是怎样把数据提交到后台处理?
根据以往,我们提交数据是通过表单,这里没有,咋搞???
还好JavaScript 给我们提供了方法来构建html 元素。
直接上代码
function new_form(){
var f = document.createElement("form"); // 创建form
document.body.appendChild(f); //追加到body下
f.method = "post"; //设置提交方式 post
return f; // 返回对象
}
function create_elements(eForm,eName,eValue){
var e=document.createElement("input"); // 给form 创建input
eForm.appendChild(e); // input 追加到 form内
e.name=eName; //设置 input name的值
if(!document.all){ // css 样式设置 不显示 表单
e.style.display='none';
}
e.value=eValue; // input的值
return e; // 返回对象
}
这样的话,在需要提交数据给后台的时候,我就可以构建一个表单,然后提交给后台就好。
二维数组也有了,表单构建也可以了。
但是,JavaScript的二维数组不能够直接提交到后台,我们要先作处理。利用JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。什么是JSON ? 不懂请前往学习一分钟 w3school - json
JSON 键值对是用来保存 JS 对象的一种方式,和 JS 对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号 "" 包裹,使用冒号 : 分隔,然后紧接着值:
{"firstName": "John"}
这很容易理解,等价于这条 JavaScript 语句:
{firstName: "John"}
confirm 提交代码
$('.sure').click(function(){
var data = new Array();
$('.item').each(function(index){
var foodid = $(this).children().eq(4).find('span').text();
var price = $(this).children().eq(2).children().eq(0).find('span').text();
var subTotal = $(this).children().eq(3).find('span').text();
var num = $(this).children().eq(2).find('select').children('option:selected').val();
data[index] = new Array();
data[index][0]= foodid;
data[index][1]= price;
data[index][2]= num;
data[index][3]= subTotal;
});
data = JSON.stringify(data); // 数组转 json
var _f=new_form();//创建一个form表单
create_elements(_f,"data",data);//创建form中的input对象 , 设置name 为 data, value 为 数组转json的 数据 data
_f.action="savefood.php";//form提交地址
_f.submit();
});
到此, order.php 点击提交的代码完成。
下面就到了 后台 savefood.php 处理数据了。
用json_decode() 转回数组
savefood.php
saveOrder($arr);
?>
后台存储数据
public function saveOrder($arr){
$order_datetime = date("Y-m-d h:i:s",time());//创建时间
$sql = "INSERT INTO guest_order (fid,fprice,fnum,fsubtotal,guestname,order_datetime)VALUES ";
//构建拼接 sql 语句
for ($i=0; $i < count($arr); $i++) {
//这里判断数量是否为0,如果是则跳过该次循环
if ($arr[$i][2] == "0") {
continue;
}
$sql = $sql . '("'.$arr[$i][0].'" , "'.$arr[$i][1].'" , "'.$arr[$i][2].'" , "'.$arr[$i][3].'" , '. '"hj"'.',"' .$order_datetime.'"),';
}
$sql=substr($sql, 0,strlen($sql)-1);
$result = mysql_query($sql,$this->conn);
return $result;
}
至此,用户的订单可以保存到数据库的操作完成。
下面到 管理员查看订单 以及订单详情
getOrderList()
public function getOrderList(){
$sql = "SELECT guestname,sum(fsubtotal) as total,order_datetime FROM `guest_order` group by order_datetime";
$result = mysql_query($sql,$this->conn);
return $result;
}
orderlist.php
getOrderList();
?>
Order List
User
Total
Datetime
Detail
view
订单详情
orderDetail($user,$datetime)
public function orderDetail($user,$datetime){
$sql = 'SELECT * FROM `guest_order` JOIN food on guest_order.fid = food.id WHERE guest_order.order_datetime = "'.$datetime.'" and guest_order.guestname="'.$user.'"';
$result = mysql_query($sql,$this->conn);
return $result;
}
orderdetail.php
orderDetail($user,$datetime);
?>
Bootstrap 101 Template
你好,世界!
Order List
--
Image
Name
Price
Num
SubTotal
Total :
以上为全部代码,希望有所帮助。