PHP 購物車 session (ThinkPHP)
本篇文章為ThinkPHP框架實現購物車,上一篇文章為非框架實現購物車。
這是我的一次面試中的面試題,簡單寫商城的購物車功能,要求是:
1、自己寫簡單的前臺
2、使用者登入前能用購物車
3、不可以用cookie
暫時瞭解到的解決方法有三個:
1、cookie
2、session
3、資料庫
該購物車的主要邏輯是,用session來實現識別不同的使用者各自的購物車,以便使用者登入後儲存的是自己的購物車。流程圖如下:
ThinkPHP框架下,實現該購物車功能相對非框架的實現更加簡單快捷一些,主要是兩個控制器檔案分別是商品控制器GoodsContoller.class.php以及使用者控制器IndexControllerr.class.php
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則不會清空。