zoukankan      html  css  js  c++  java
  • ThinkPHP5+Redis实现购物车

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

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

    参考文章:

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

     二、附上代码

    1、前端

    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
        <meta charset="utf-8">
    </head>
    <body>
    <h3>我的购物车</h3>
    <form action="/index/index/index" method="post">
        
        <input type="text" name="ids">
        <input type="submit" value="获取部分商品信息">
        <span style="color: gray; font-size: 14px;">用英文逗号隔开</span>
    </form>
    所选商品数量:{$totalnum}
    <br><br>
    
    <form action="/index/index/emptyCart">
        <input type="submit" value="清空购物车">
    </form>
    <br>
    
    <table border="1">
        <tr align="center">
            <td style=" 100px">商品ID</td>
            <td style=" 100px">商品属性ID</td>
            <td style=" 100px">商品名</td>
            <td style=" 100px">商品属性名称</td>
            <td style=" 100px">数量</td>
            <td style=" 100px">单价</td>
            <td style=" 100px">运费</td>
            <td style=" 100px">总价</td>
            <td style=" 100px">操作</td>
        </tr>
        {volist name="list" id="vo"}
        <tr align="center">
            <td style=" 100px">{$vo.goods_id}</td>
            <td style=" 100px">{$vo.attr_id}</td>
            <td style=" 100px">{$vo.goods_name}</td>
            <td style=" 100px">{$vo.attr_name}</td>
            <td style=" 100px">{$vo.goods_number}</td>
            <td style=" 100px">{$vo.price}</td>
            <td style=" 100px">{$vo.freight}</td>
            <td style=" 100px">{$vo.subtotal}</td>
            <td style=" 100px"><a href="/index/index/del.html?id={$vo.goods_id}">删除</a></td>
        </tr>
        {/volist}
    </table>
    
    <br/>
    <hr/>
    
    
    <h3>添加购物车</h3>
    
    <form action="/index/index/addbasket" method="post">
        
        商品ID:<input type="text" name="goods_id" value="111">
        商品属性ID:<input type="text" name="attr_id" value="222">
        商品名:<input type="text" name="goods_name" value="U盘">
        商品属性名称:<input type="text" name="attr_name" value="数码类">
        <br/><br/>&nbsp; &nbsp;量:<input type="text" name="number" value="1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;价:<input type="text" name="price" value="12">&nbsp; 费:<input type="text" name="freight" value="10">
    
        <input type="submit" value="添加购物车">
    </form>
    
    <br/>
    <hr/>
    
    <h3>某一商品减一</h3>
    <form action="/index/index/reduce" method="post">
        商品ID:<input type="text" name="id"> 
        商品属性ID:<input type="text" name="attr_id"> 
        减去数量:<input type="text" name="number"> 
        <input type="submit" value="减一">
    </form>
    <br/>
    <hr/>
    
    <h3>编辑商品</h3>
    <form action="/index/index/edit" method="post">
        商品ID:<input type="text" name="id"> 
        商品属性ID:<input type="text" name="attr_id"> 
        修改数量:<input type="text" name="number"> 
        <input type="submit" value="修改">
    </form>
    <br/>
    <hr/>
    
    </body>
    </html>

    2、后端代码

    <?php
    namespace appindexcontroller;
    use thinkController;
    use thinkcachedriverRedis;
    
    class Index extends Controller
    {
    
        private $expire = 43200;    //redis缓存过期时间  12h
        private $redis = null;
        private $cachekey = null;    //缓存变量名
        private $basket = [];        //私有数组,存放商品信息
    
        private $user_id = '110';
        
        /**
         * 购物车初始化,传入用户id
         */
        public function __construct()
        {
            parent::__construct();
    
            $this->redis = new Redis();        // 实例化
            $this->redis->connect('127.0.0.1','6379');
            $this->redis->auth('zxf123456');
    
            $this->cachekey = 'user'.$this->user_id.'.cart';    //redis缓存键名拼接用户id与字符串为对象用户购物车缓存键名  user110.cart
            $this->basket = json_decode($this->redis->get($this->cachekey),true);    //获取对象用户的redis购物车商品缓存信息并解码为数组
        }
    
        /**
         * 获取所有商品信息
         */
        public function index()
        {
            $ids = input('post.ids');
            // 如果获取部分商品信息(搜索进来)
            if (!empty($ids)) {
    
                // 获取部分商品信息
                $list = $this->getPartGoods($ids);
    
                // 获取部分商品数量
                $totalnum = $this->getPartGoodsNum($ids);
    
            }else{
                // 默认全部列表
                $list = $this->basket;
                // 获取所有商品数量
                $totalnum = $this->getAllDoodsNum();
            }
            $this->assign(['list'=>$list,'totalnum'=>$totalnum]);
            return $this->fetch();
        }
    
        /**
         * 添加商品到购物车
         * @param 商品id 商品属性id 商品名称 数量 价格
         */
        public function addbasket()
        {
    
            $data = request()->param();
            // 判断对象是否已经存在redis购物车缓存中
            if ($this->isExist($data['goods_id'],$data['attr_id'])) {
    
                // 存在缓存中,增加该商品数量
                return $this->add($data['goods_id'],$data['attr_id'],$data['number']);
            }
    
            // 对象商品不在redis缓存中时
            $tmp = [];
            $tmp['goods_id'] = intval($data['goods_id']);    //商品id
            $tmp['attr_id'] = intval($data['attr_id']);    //商品属性id
            $tmp['goods_name'] = $data['goods_name'];        //商品名
            $tmp['attr_name'] = $data['attr_name'];            //商品属性名称
            $tmp['goods_number'] = intval($data['number']);            //商品数量,新增的商品默认加入数量为1
            $tmp['price'] = intval($data['price']);            //商品价格
            $tmp['freight'] = intval($data['freight']);        //运费
    
            $tmp['subtotal'] = $tmp['goods_number'] * $tmp['price'] + $tmp['freight'];    //商品总价
    
            $this->basket[] = $tmp;        // 把新的商品信息追加到之前的商品缓存数组中,每件属性商品对应一个索引键值
    
            
            // 把新的购物车信息编码为json字符串,并重新存入到redis购物车缓存中
            $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
    
            // return 1;
            echo "<script>alert('添加成功');window.location.replace(document.referrer);;</script>";
        }
    
        /**
         * 判断商品是否已经存在
         * @param 商品id 商品属性id
         */
        public function isExist($id,$attr_id)
        {
            $isExist = false;
            // 当对象用户redis购物车商品缓存不为空时
            if (!empty($this->basket)) {
    
                foreach ($this->basket as $key => $value) {
                    // 判断当前商品是否存在
                    if ($value['goods_id'] == $id && $value['attr_id'] == $attr_id) {
                        $isExist = true;
                        break;
                    }
                }
            }
            return $isExist;
        }
    
        /**
         * 添加商品
         */
        public function add($id,$attr_id,$number)
        {
    
            $goods_number = 0;    //加入不成功时默认添加数量为0
            // 商品id不为空并且商品在redis购物车商品缓存中
            if (!empty($id) && $this->isExist($id,$attr_id)) {
    
                $cache_detail = $this->basket;        //获取用户购物车所有商品
                foreach ($cache_detail as $key => $value) {
    
                    if ($value['goods_id'] == $id && $value['attr_id'] == $attr_id) {
    
                        // 只修改商品数量和总价
                        $value['goods_number'] = $value['goods_number'] + $number;    //增加购物车商品数量
                        $value['subtotal'] = $value['goods_number'] * $value['price'] + $value['freight'];    //重新计算总价  数量*单价+运费
     
    
                        $this->basket[$key] = $value;    //把该商品重新放到redis缓存中
                        $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
    
                        $goods_number = $value['goods_number'];
                        break;
    
                    }
                }
            }
            return $goods_number;    //返回商品数量
        }
    
        /**
         * 获取部分商品
         */
        public function getPartGoods($ids)
        {
            // 字符串转数组
            $ids = explode(',', $ids);
            $goods = [];
            // 循环ids数组,循环redis缓存数组,当商品id一致时,取出来存到goods数组中
            foreach ($ids as $v) {
                foreach ($this->basket as $key => $value) {
                    if ($value['goods_id'] == $v) {
    
                        $goods[] = $value;
                    }
                }
            }
            return $goods;
        }
    
        /**
         * 获取部分商品总数
         */
        public function getPartGoodsNum($ids)
        {
            // 字符串转数组
            $ids = explode(',', $ids);
            $number = 0;    //默认为0
            foreach ($ids as $v) {
    
                foreach ($this->basket as $key => $value) {
    
                    // 取出redis缓存中有该id的商品数量
                    if ($value['goods_id'] == $v) {
                        $number += $value['goods_number'];
                    }
                }
            }
            return $number;
        }
    
        /**
         * 获取全部商品数量
         */
        public function getAllDoodsNum()
        {
            $number = 0;
            if (!empty($this->basket)) {
                foreach ($this->basket as $key => $value) {
                    $number += $value['goods_number'];
                }
            }
            return $number;
        }
    
        /**
         * 某一商品数量减一
         */
        public function reduce()
        {
            $data = request()->param();
            $goods_number = 0;    //默认减0
    
            // 如果接收的数据不为空,并且该商品信息存在
            if (!empty($data) && $this->isExist($data['id'],$data['attr_id'])) {
    
                // 获取redis缓存里的数据
                $cache_detail = $this->basket;
    
                // 循环判断,从缓存商品列表中找到该条商品,数量并减一
                foreach ($cache_detail as $key => $value) {
                    if ($value['goods_id'] == $data['id'] && $value['attr_id'] == $data['attr_id']) {
    
                        // 先判断当前商品的数量是否大于要删除的数量
                        if ($value['goods_number'] < $data['number']) {
    
                            echo "<script>alert('商品数量不足');window.history.back();</script>";
                            break;
                        }
                        // 如果当前商品数量为1,则删除
                        if ($value['goods_number'] <= 1) {
    
                            // 循环判断找出该商品,并删除
                            foreach ($this->basket as $key => $value) {
                                if ($value['goods_id'] == $data['id']) {
                                    // 从数组中移除当前商品
                                    array_splice($this->basket, $key, 1);
                                }
                            }
                            // 重新存入缓存
                            $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
                            $goods_number = 0;
    
                        }else{
    
                            // 数量减
                            $value['goods_number'] = $value['goods_number'] - $data['number'];
                            $goods_number = $value['goods_number'];
                            // 计算总价
                            $value['subtotal'] = $value['goods_number'] * $value['price'];
                            
                            // 把新的数据追加到$this->basket
                            $this->basket[$key] = $value;
    
                            // 重新存入缓存
                            $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
                        }
                    }
                }
            }
            // return $goods_number;
            echo "该商品当前数量为".$goods_number;
        }
    
        /**
         * 删除商品
         */
        public function del()
        {
            $id = input('id');
            // 循环判断,并删除
            foreach ($this->basket as $key => $value) {
                if ($value['goods_id'] == $id) {
                    // 从数组中移除当前商品
                    array_splice($this->basket, $key, 1);
                }
            }
            $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
            // return true;
            echo "<script>alert('删除成功');window.location.replace(document.referrer);;</script>";
        }
    
        /**
         * 编辑商品
         */
        public function edit()
        {
            $data = input('post.');
            if (!empty($data) && $this->isExist($data['id'],$data['attr_id']) && $data['number'] > 0) {
    
                // 取出缓存中的数据
                $cache_detail = $this->basket;
    
                // 循环判断,取出当前商品信息,并修改
                foreach ($cache_detail as $key => $value) {
    
                    if ($value['goods_id'] == $data['id'] & $value['attr_id'] == $data['attr_id']) {
    
                        // 商品数量
                        $value['goods_number'] = intval($data['number']);
                        // 商品总价 数量*单价+运费
                        $value['subtotal'] = $value['goods_number'] * $value['price'] + $value['freight'];
                        // 赋值
                        $this->basket[$key] = $value;
    
                        // 重新存储到缓存
                        $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
                        echo "该商品当前数量为".$value['goods_number'];
                    }
                }
            }
        }
    
        /**
         * 清空购物车
         */
        public function emptyCart()
        {
            $this->redis->rm($this->cachekey);
            echo "<script>alert('购物车清空成功');window.location.replace(document.referrer);;</script>";
        }
    
    }

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

    三、常见错误

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

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

    其他弃用函数

  • 相关阅读:
    C#+Arcengine创建内存图层
    Creating a Feature Set via C#
    ArcGIS Server for JavaScript api安装部署
    Lucene.Net 3.0.3如何从TokenStream中获取token对象
    MMSEG 中文算法说明
    java DotNet char 代码对应
    Lucene.Net 3.0.3如何从TokenStream中获取token对象
    java DotNet char 代码对应
    9.7
    9.6
  • 原文地址:https://www.cnblogs.com/zxf100/p/14171585.html
Copyright © 2011-2022 走看看