这是我的一次面试中的面试题,简单写商城的购物车功能,要求是:
1、自己写简单的前台
2、用户登录前能用购物车
3、不可以用cookie
暂时了解到的解决方法有三个:
1、cookie
2、session
3、数据库
该购物车的主要逻辑是,用session来实现识别不同的用户各自的购物车,以便用户登录后保存的是自己的购物车。流程图如下:
ThinkPHP框架下,实现该购物车功能相对非框架的实现更加简单快捷一些,主要是两个控制器文件分别是商品控制器GoodsContoller.class.php以及用户控制器IndexControllerr.class.php,以及三个视图模板文件分别是商品展示模板showlist.html 购物车内容模板shop_cart.html 登录界面模板login.html 至于数据表只需要建立三个,一个是用户表user 一个是商品表 goods 最后一个是订单表buy
GoodsController.class.php
<span style="font-size:12px;"><?php
namespace Home\Controller;
use Think\Controller;
Class GoodsController extends Controller {
//展示商品内容的的方法
public function showlist() {
$goods = D('goods');
$goods_list = $goods->order('goods_id desc')->select();
$this->assign('goods_list', $goods_list);
$this->display();
}
//展示已添加到购物车的商品的方法,把已添加的商品暂时存放在一组二维数组数组当中array(‘商品名字’ => array(商品信息))
public function shop_cart() {
session_start(); //开启session
$GET_name = I('get.goods_name');
$GET_id = I('get.goods_id');
$shop_cart = I('session.shop_cart'); //读取session并放在数组$shop_cart
//判断session数组中是否存在过该添加购物车的商品
if (array_key_exists($GET_name, $shop_cart)) {
//该商品已经添加过购物车,进行shop_cart数组中的该商品数量加1的操作
$shop_cart[$GET_name]['goods_num'] ++;
} else {
//该商品为新商品,进行数据库查询该商品具体信息,并存入shop_cart数组
$goods = D('goods');
$result = $goods->where(array('goods_id' => array('eq', $GET_id)))->select();
$arr0 = array($GET_name => array('goods_id' => $GET_id, 'goods_num' => 1, 'goods_name' => $GET_name, 'goods_price' => $result[0]['goods_price']));
foreach ($arr0 as $key => $value) {
$shop_cart[$key] = $value;
}
}
session('shop_cart', $shop_cart); //赋值给session
//var_dump($shop_cart);
$this->assign('shop_cart', $shop_cart);
$this->display();
}
//清空当前购物车的方法
public function clean_cart() {
session('shop_cart', null);
redirect(U('showlist'), 2, '已成功清空购物车,正在跳转到商城首页。。。。。');
}
//结算方法
public function finish() {
//通过session['user_name']判断是否登录。如果已登录则把数据写入数据库,并提示成功跳转到商品展示页
//如果未登录 ,提示进行登录,并且跳转至登录页面
session_start(); //开启session
$buy = D('buy');
$shop_cart = session('shop_cart'); //从session中读取购物车二维数组
$user_name = session('user_name'); //从session中读取用户的信息
if (isset($user_name)) {
//已经登录,从session中取出数据来写入数据库
foreach ($shop_cart as $v => $val) {
$data['buy_goods_id'] = $val['goods_id'];
$data['buy_goods_name'] = $val['goods_name'];
$data['buy_goods_num'] = $val['goods_num'];
$data['buy_goods_price'] = $val['goods_price'];
$data['user_name'] = $user_name;
$rs = $buy->add($data);
}
if ($rs)
$this->success('结算成功!!!现在返回首页', U('showlist'), 2); //成功写入数据则提示并2秒后跳转
else
$this->error('结算失败,正在返回购物车!!!', U('shop_cart'), 3); //失败写入数据则提示并3秒后跳转
}else {
//未登录则重定向到登录页面
redirect(U('Index/login'), 2, '请登录后再进行结算,界面正跳转到登录界面。。。');
}
}
}
?></span>
IndexController.class.php
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
public function index() {
$this ->display(U('Goods/showlist'));
}
public function login() {
$this->display();
}
public function logout() {
session('user_name', null);
redirect(U('Goods/showlist'), 2, '已成功退出,正在返回商城首页。。。。。');
}
public function check_login() {
session_start(); //开启session
$user = D('user');
$user_name = I('post.user_name');
$user_pwd = I('post.user_pwd');
//查询数据库,并先验证用户名是否正确,若正确再进行下一步验证密码
$result = $user->where(array('user_name' => array('eq', $user_name)))->select();
if ($result) {
if ($result[0]['user_pwd'] == $user_pwd) {
session('user_name', $user_name); //把用户名添加到session中
redirect(U('Goods/showlist'), 1, '正在登录中。。。。');
} else {
redirect(U('login'), 2, '密码错误!请重新登录。');
}
} else {
redirect(U('login'), 2, '不存在该用户,请重新登录。');
}
}
}
shoplist.html
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
当前用户:
<a style="font-size: 150%;color: red;" >
<?php
if(isset($_SESSION['user_name']))
echo $_SESSION['user_name'] . " ";
else
echo '未登录';
?>
</a>
<a style="font-size: 150%;color: #f0c040" href="__CONTROLLER__/showlist" >继续购物</a>
</br>
</br>
<a style="font-size: 150%;color: blue" >购物车状态:</a>
<table border="1" height="400px" width="400px">
<td style="font-size: 120%;color: blue;text-align: center">商品id</td>
<td style="font-size: 120%;color: blue;text-align: center">商品名字</td>
<td style="font-size: 120%;color: blue;text-align: center">商品数量</td>
<td style="font-size: 120%;color: blue;text-align: center">商品价格</td>
<volist name="shop_cart" id="val">
<tr>
<td width="50px"><?php echo $val['goods_id']?></td>
<td ><?php echo $val['goods_name']?></td>
<td ><?php echo $val['goods_num']?></td>
<td ><?php echo $val['goods_price']?></td>
</tr>
</volist>
</table>
<form name="myform" method="POST" action="__CONTROLLER__/finish">
<input type="hidden" name="goods_id" value=" $val['goods_id']" /><br/>
<input type="hidden" name="goods_name" value="$val['goods_name']" /><br/>
<input type="hidden" name="goods_num" value="$val['goods_num']" /><br/>
<input type="hidden" name="goods_price" value="$val['goods_price']" />
<input type="submit" name="sub" style="font-size: 200%;color: red" value="结算购物车" />
<a href="__CONTROLLER__/clean_cart"><input type="button" value="清空购物车" style="font-size: 200%;color: red"></a>
</form>
</body>
</html>
shop_cart.html
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
当前用户:<a style="font-size: 150%;color: red" >
<?php
if(isset($_SESSION['user_name'])){
echo $_SESSION['user_name'];
?>
<a href="__MODULE__/Index/logout">(退出登录)</a>
<?php
}else{
echo '未登录';
?>
<a href="__MODULE__/Index/login">(登录)</a>
<?php }?>
</a>
<a style="font-size: 150%;color: blue" href="__CONTROLLER__/shop_cart">购物车内容</a>
</br></br>
<a style="font-size: 150%;color: blue">商品列表:</a>
<table border="1" height="400px" width="400px">
<td style="font-size: 120%;color: blue;text-align: center">商品id</td>
<td style="font-size: 120%;color: blue;text-align: center">商品名字</td>
<td style="font-size: 120%;color: blue;text-align: center">商品数量</td>
<td style="font-size: 120%;color: blue;text-align: center">商品价格</td>
<td style="font-size: 120%;color: blue;text-align: center">操作</td>
<volist name="goods_list" id="v1">
<tr>
<td width="50px">{$v1.goods_id}</td>
<td >{$v1.goods_name}</td>
<td >{$v1.goods_num}</td>
<td >{$v1.goods_price}</td>
<td style="font_size:150%;color: red;text-align:center" >
<a href="__CONTROLLER__/shop_cart?goods_name={$v1.goods_name}&goods_id={$v1.goods_id}">加入购物车
</td>
</tr>
</volist>
</table>
</body>
</html>
login.html
<html>
<head>
<meta charset="utf-8"/>
<title>用户登陆</title>
</head>
<body>
<h1>请进行商城用户登录:</h1>
<form name="myform" method="POST" action="__CONTROLLER__/check_login">
用户名:<input type="text" name="user_name" value="" /><br/>
密码 :<input type="password" name="user_pwd" value="" /><br/>
<input type="submit" name="sub" value="用户登陆" />
</form>
</body>
</html>
shoppingcart.sql(该文件不是工具直接导出,所以需要手动复制代码创建)
--shoppingCart.sql
--该文件为记录此商城所需要建立的数据库的各种表以及数据
CREATE DATABASE `ShoppingCart`;
--Goods表
DROP TABLE IF EXISTS `Goods`;
CREATE TABLE `Goods`(
`goods_id` tinyint(4) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`goods_name` varchar(20) NOT NULL COMMENT '商品名字',
`goods_num` smallint(6) unsigned NOT NULL COMMENT '商品剩余数量',
`goods_Price` smallint(6) unsigned NOT NULL COMMENT '商品价格'
)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
--用户表
DROP TABLE IF EXISTS `User`;
CREATE TABLE `User`(
`user_id` tinyint(4) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`user_name` varchar(20) NOT NULL COMMENT '用户名',
`user_pwd` varchar(20) NOT NULL COMMENT '用户密码'
)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
--订单表
CREATE TABLE `Buy`(
`buy_goods_id` tinyint(4) unsigned NOT NULL ,
`buy_goods_name` varchar(20) NOT NULL COMMENT '商品名字',
`buy_goods_num` smallint(6) unsigned NOT NULL COMMENT '商品购买数量',
`buy_goods_Price` smallint(6) unsigned NOT NULL COMMENT '商品价格',
`user_name` varchar(20) NOT NULL COMMENT '订单提交者'
)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
--用户表
insert into `Goods` values(1,'Nokia',100,2000);
insert into `Goods` values(2,'Samsung',150,3000);
insert into `Goods` values(3,'Apple',200,4000);
insert into `User` values(1,'Tim','123');
insert into `User` values(2,'Jack','123');
insert into `User` values(3,'Tom','123');
值得注意的是,因为该项目只是实现了购物车的功能,也没有真正意义上的商城默认首页,所以应该把配置文件中的ThinkPHP默认控制器修改成GoodsController,以及默认操作修改成showlist。从而实现用户打开网站的首页就是展示商品GoodsController/showlist。
'DEFAULT_CONTROLLER' => 'Goods', // 默认控制器名称
'DEFAULT_ACTION' => 'showlist', // 默认操作名称
总结:
其实购物车的逻辑很简单,由于ThinkPHP框架先天优势,MVC模式使得逻辑相对非框架更清晰明了。主要是解决如何识别每一个没登录用户的身份,这有三种方案解决,分别是1、cookie 2、session 3、数据库 ;这一点用session就很容易解决,相对COOKIE的解决方案优点是不会因为用户禁用了本机的cookie功能而导致购物车功能作废;session把数据存放在了服务器,安全性也有一定的提高;不过session也不是完全没有缺点,如果并发用户很多的时候,会在服务器生成大量的session,占用服务器的资源同时也影响服务器的性能。而且当用户退出浏览器的时候,购物车session就会清空,而cookie则不会清空。