经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » PHP » 查看文章
ThinkPHP5+Redis实现购物车
来源:cnblogs  作者:下页、再停留  时间:2020/12/22 11:10:57  对本文有异议

本篇文章是通过ThinkPHP5和Redis实现购物车,功能包括:购物车列表、添加购物车、获取部分商品、获取部分商品总数量、获取全部商品总数量、商品减一、修改商品数量、删除商品、清空购物车,这些功能基本上能够满足购物车的需求,代码写的不够严谨,但大致逻辑就是这样。

前提:安装PHP运行环境,安装Redis,PHP安装Redis扩展,需要同时满足以上三个条件才能使用Redis。

参考文章:

一、先看一个运行截图(主要实现功能,页面没有优化)

 二、附上代码

1、前端

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title></title>
  5. <meta charset="utf-8">
  6. </head>
  7. <body>
  8. <h3>我的购物车</h3>
  9. <form action="/index/index/index" method="post">
  10. <input type="text" name="ids">
  11. <input type="submit" value="获取部分商品信息">
  12. <span style="color: gray; font-size: 14px;">用英文逗号隔开</span>
  13. </form>
  14. 所选商品数量:{$totalnum}
  15. <br><br>
  16.  
  17. <form action="/index/index/emptyCart">
  18. <input type="submit" value="清空购物车">
  19. </form>
  20. <br>
  21.  
  22. <table border="1">
  23. <tr align="center">
  24. <td style="width: 100px">商品ID</td>
  25. <td style="width: 100px">商品属性ID</td>
  26. <td style="width: 100px">商品名</td>
  27. <td style="width: 100px">商品属性名称</td>
  28. <td style="width: 100px">数量</td>
  29. <td style="width: 100px">单价</td>
  30. <td style="width: 100px">运费</td>
  31. <td style="width: 100px">总价</td>
  32. <td style="width: 100px">操作</td>
  33. </tr>
  34. {volist name="list" id="vo"}
  35. <tr align="center">
  36. <td style="width: 100px">{$vo.goods_id}</td>
  37. <td style="width: 100px">{$vo.attr_id}</td>
  38. <td style="width: 100px">{$vo.goods_name}</td>
  39. <td style="width: 100px">{$vo.attr_name}</td>
  40. <td style="width: 100px">{$vo.goods_number}</td>
  41. <td style="width: 100px">{$vo.price}</td>
  42. <td style="width: 100px">{$vo.freight}</td>
  43. <td style="width: 100px">{$vo.subtotal}</td>
  44. <td style="width: 100px"><a href="/index/index/del.html?id={$vo.goods_id}">删除</a></td>
  45. </tr>
  46. {/volist}
  47. </table>
  48.  
  49. <br/>
  50. <hr/>
  51.  
  52.  
  53. <h3>添加购物车</h3>
  54.  
  55. <form action="/index/index/addbasket" method="post">
  56. 商品ID:<input type="text" name="goods_id" value="111">
  57. 商品属性ID:<input type="text" name="attr_id" value="222">
  58. 商品名:<input type="text" name="goods_name" value="U盘">
  59. 商品属性名称:<input type="text" name="attr_name" value="数码类">
  60. <br/><br/>
  61. &nbsp; &nbsp;量:<input type="text" name="number" value="1">
  62. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;价:<input type="text" name="price" value="12">
  63. &nbsp; 费:<input type="text" name="freight" value="10">
  64.  
  65. <input type="submit" value="添加购物车">
  66. </form>
  67.  
  68. <br/>
  69. <hr/>
  70.  
  71. <h3>某一商品减一</h3>
  72. <form action="/index/index/reduce" method="post">
  73. 商品ID:<input type="text" name="id">
  74. 商品属性ID:<input type="text" name="attr_id">
  75. 减去数量:<input type="text" name="number">
  76. <input type="submit" value="减一">
  77. </form>
  78. <br/>
  79. <hr/>
  80.  
  81. <h3>编辑商品</h3>
  82. <form action="/index/index/edit" method="post">
  83. 商品ID:<input type="text" name="id">
  84. 商品属性ID:<input type="text" name="attr_id">
  85. 修改数量:<input type="text" name="number">
  86. <input type="submit" value="修改">
  87. </form>
  88. <br/>
  89. <hr/>
  90.  
  91. </body>
  92. </html>

2、后端代码

  1. <?php
  2. namespace app\index\controller;
  3. use think\Controller;
  4. use think\cache\driver\Redis;
  5. class Index extends Controller
  6. {
  7. private $expire = 43200; //redis缓存过期时间
  8. private $redis = null;
  9. private $cachekey = null; //缓存变量名
  10. private $basket = []; //私有数组,存放商品信息
  11.  
  12. private $user_id = '110';
  13. /**
  14. * 购物车初始化,传入用户id
  15. */
  16. public function __construct()
  17. {
  18. parent::__construct();
  19. // redis连接参数
  20. $opt['host'] = '127.0.0.1';
  21. $opt['port'] = 6379;
  22. $opt['password'] = 'zxf123456';
  23. $this->redis = new Redis($opt); // 实例化
  24. $this->cachekey = 'user'.$this->user_id.'.cart'; //redis缓存键名拼接用户id与字符串为对象用户购物车缓存键名 user110.cart
  25. $this->basket = json_decode($this->redis->get($this->cachekey),true); //获取对象用户的redis购物车商品缓存信息并解码为数组
  26. }
  27. /**
  28. * 获取所有商品信息
  29. */
  30. public function index()
  31. {
  32. $ids = input('post.ids');
  33. // 如果获取部分商品信息(搜索进来)
  34. if (!empty($ids)) {
  35. // 获取部分商品信息
  36. $list = $this->getPartGoods($ids);
  37. // 获取部分商品数量
  38. $totalnum = $this->getPartGoodsNum($ids);
  39. }else{
  40. // 默认全部列表
  41. $list = $this->basket;
  42. // 获取所有商品数量
  43. $totalnum = $this->getAllDoodsNum();
  44. }
  45. $this->assign(['list'=>$list,'totalnum'=>$totalnum]);
  46. return $this->fetch();
  47. }
  48. /**
  49. * 添加商品到购物车
  50. * @param 商品id 商品属性id 商品名称 数量 价格
  51. */
  52. public function addbasket()
  53. {
  54. $data = request()->param();
  55. // 判断对象是否已经存在redis购物车缓存中
  56. if ($this->isExist($data['goods_id'],$data['attr_id'])) {
  57. // 存在缓存中,增加该商品数量
  58. return $this->add($data['goods_id'],$data['attr_id'],$data['number']);
  59. }
  60. // 对象商品不在redis缓存中时
  61. $tmp = [];
  62. $tmp['goods_id'] = intval($data['goods_id']); //商品id
  63. $tmp['attr_id'] = intval($data['attr_id']); //商品属性id
  64. $tmp['goods_name'] = $data['goods_name']; //商品名
  65. $tmp['attr_name'] = $data['attr_name']; //商品属性名称
  66. $tmp['goods_number'] = intval($data['number']); //商品数量,新增的商品默认加入数量为1
  67. $tmp['price'] = intval($data['price']); //商品价格
  68. $tmp['freight'] = intval($data['freight']); //运费
  69.  
  70. $tmp['subtotal'] = $tmp['goods_number'] * $tmp['price'] + $tmp['freight']; //商品总价
  71.  
  72. $this->basket[] = $tmp; // 把新的商品信息追加到之前的商品缓存数组中,每件属性商品对应一个索引键值
  73. // 把新的购物车信息编码为json字符串,并重新存入到redis购物车缓存中
  74. // $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
  75. $this->redis->set($this->cachekey,json_encode($this->basket));
  76. // return 1;
  77. echo "<script>alert('添加成功');window.location.replace(document.referrer);;</script>";
  78. }
  79. /**
  80. * 判断商品是否已经存在
  81. * @param 商品id 商品属性id
  82. */
  83. public function isExist($id,$attr_id)
  84. {
  85. $isExist = false;
  86. // 当对象用户redis购物车商品缓存不为空时
  87. if (!empty($this->basket)) {
  88. foreach ($this->basket as $key => $value) {
  89. // 判断当前商品是否存在
  90. if ($value['goods_id'] == $id && $value['attr_id'] == $attr_id) {
  91. $isExist = true;
  92. break;
  93. }
  94. }
  95. }
  96. return $isExist;
  97. }
  98. /**
  99. * 添加商品
  100. */
  101. public function add($id,$attr_id,$number)
  102. {
  103. $goods_number = 0; //加入不成功时默认添加数量为0
  104. // 商品id不为空并且商品在redis购物车商品缓存中
  105. if (!empty($id) && $this->isExist($id,$attr_id)) {
  106. $cache_detail = $this->basket; //获取用户购物车所有商品
  107. foreach ($cache_detail as $key => $value) {
  108. if ($value['goods_id'] == $id && $value['attr_id'] == $attr_id) {
  109. // 只修改商品数量和总价
  110. $value['goods_number'] = $value['goods_number'] + $number; //增加购物车商品数量
  111. $value['subtotal'] = $value['goods_number'] * $value['price'] + $value['freight']; //重新计算总价 数量*单价+运费
  112.  
  113. $this->basket[$key] = $value; //把该商品重新放到redis缓存中
  114. $this->redis->set($this->cachekey,json_encode($this->basket)); //更新redis缓存
  115.  
  116. $goods_number = $value['goods_number'];
  117. break;
  118. }
  119. }
  120. }
  121. return $goods_number; //返回商品数量
  122. }
  123. /**
  124. * 获取部分商品
  125. */
  126. public function getPartGoods($ids)
  127. {
  128. // 字符串转数组
  129. $ids = explode(',', $ids);
  130. $goods = [];
  131. // 循环ids数组,循环redis缓存数组,当商品id一致时,取出来存到goods数组中
  132. foreach ($ids as $v) {
  133. foreach ($this->basket as $key => $value) {
  134. if ($value['goods_id'] == $v) {
  135. $goods[] = $value;
  136. }
  137. }
  138. }
  139. return $goods;
  140. }
  141. /**
  142. * 获取部分商品总数
  143. */
  144. public function getPartGoodsNum($ids)
  145. {
  146. // 字符串转数组
  147. $ids = explode(',', $ids);
  148. $number = 0; //默认为0
  149. foreach ($ids as $v) {
  150. foreach ($this->basket as $key => $value) {
  151. // 取出redis缓存中有该id的商品数量
  152. if ($value['goods_id'] == $v) {
  153. $number += $value['goods_number'];
  154. }
  155. }
  156. }
  157. return $number;
  158. }
  159. /**
  160. * 获取全部商品数量
  161. */
  162. public function getAllDoodsNum()
  163. {
  164. $number = 0;
  165. if (!empty($this->basket)) {
  166. foreach ($this->basket as $key => $value) {
  167. $number += $value['goods_number'];
  168. }
  169. }
  170. return $number;
  171. }
  172. /**
  173. * 某一商品数量减一
  174. */
  175. public function reduce()
  176. {
  177. $data = request()->param();
  178. $goods_number = 0; //默认减0
  179. // 如果接收的数据不为空,并且该商品信息存在
  180. if (!empty($data) && $this->isExist($data['id'],$data['attr_id'])) {
  181. // 获取redis缓存里的数据
  182. $cache_detail = $this->basket;
  183. // 循环判断,从缓存商品列表中找到该条商品,数量并减一
  184. foreach ($cache_detail as $key => $value) {
  185. if ($value['goods_id'] == $data['id'] && $value['attr_id'] == $data['attr_id']) {
  186. // 先判断当前商品的数量是否大于要删除的数量
  187. if ($value['goods_number'] < $data['number']) {
  188. echo "<script>alert('商品数量不足');window.history.back();</script>";
  189. break;
  190. }
  191. // 如果当前商品数量为1,则删除
  192. if ($value['goods_number'] <= 1) {
  193. // 循环判断找出该商品,并删除
  194. foreach ($this->basket as $key => $value) {
  195. if ($value['goods_id'] == $data['id']) {
  196. // 从数组中移除当前商品
  197. array_splice($this->basket, $key, 1);
  198. }
  199. }
  200. // 重新存入缓存
  201. $this->redis->set($this->cachekey,json_encode($this->basket));
  202. $goods_number = 0;
  203. }else{
  204. // 数量减
  205. $value['goods_number'] = $value['goods_number'] - $data['number'];
  206. $goods_number = $value['goods_number'];
  207. // 计算总价
  208. $value['subtotal'] = $value['goods_number'] * $value['price'];
  209. // 把新的数据追加到$this->basket
  210. $this->basket[$key] = $value;
  211. // 重新存入缓存
  212. $this->redis->set($this->cachekey,json_encode($this->basket));
  213. }
  214. }
  215. }
  216. }
  217. // return $goods_number;
  218. echo "该商品当前数量为".$goods_number;
  219. }
  220. /**
  221. * 删除商品
  222. */
  223. public function del()
  224. {
  225. $id = input('id');
  226. // 循环判断,并删除
  227. foreach ($this->basket as $key => $value) {
  228. if ($value['goods_id'] == $id) {
  229. // 从数组中移除当前商品
  230. array_splice($this->basket, $key, 1);
  231. }
  232. }
  233. $this->redis->set($this->cachekey,json_encode($this->basket));
  234. // return true;
  235. echo "<script>alert('删除成功');window.location.replace(document.referrer);;</script>";
  236. }
  237. /**
  238. * 编辑商品
  239. */
  240. public function edit()
  241. {
  242. $data = input('post.');
  243. if (!empty($data) && $this->isExist($data['id'],$data['attr_id']) && $data['number'] > 0) {
  244. // 取出缓存中的数据
  245. $cache_detail = $this->basket;
  246. // 循环判断,取出当前商品信息,并修改
  247. foreach ($cache_detail as $key => $value) {
  248. if ($value['goods_id'] == $data['id'] & $value['attr_id'] == $data['attr_id']) {
  249. // 商品数量
  250. $value['goods_number'] = intval($data['number']);
  251. // 商品总价 数量*单价+运费
  252. $value['subtotal'] = $value['goods_number'] * $value['price'] + $value['freight'];
  253. // 赋值
  254. $this->basket[$key] = $value;
  255. // 重新存储到缓存
  256. $this->redis->set($this->cachekey,json_encode($this->basket));
  257. echo "该商品当前数量为".$value['goods_number'];
  258. }
  259. }
  260. }
  261. }
  262. /**
  263. * 清空购物车
  264. */
  265. public function emptyCart()
  266. {
  267. $this->redis->rm($this->cachekey);
  268. echo "<script>alert('购物车清空成功');window.location.replace(document.referrer);;</script>";
  269. }
  270. }

有一点需要注意:“use think\cache\driver\Redis;”把redis引进来,这个Redis文件是TP5自带的,不用下载就可以直接用。代码里有注释,其他的就不再说明了,其他文件也没有什么需求配置的

 

三、常见错误

列一下我在使用过程中遇到的问题

  1. 在“清空购物车”这个功能里,有一句“ $this->redis->rm($this->cachekey);”,执行这句的时候会报错,"Function Redis::delete() is deprecated",意思是delete()这个函数已经被弃用了,可以查找到Redis文件里rm()这个函数,里面用到了delete()这个函数,只需要把delete()改成del就可以了,因为php-redis 5 已经把这个函数弃用了

其他弃用函数

原文链接:http://www.cnblogs.com/zxf100/p/14171585.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号