ThinkPHP5+Redis单例型购物车

<?php
/**
 * Redis + 单例型购物车
 * param $basket 存储商品信息
 * param $ins 存储实例化对象
 */
namespace lib;

use redis\Redis;
class Cart{
    private $expire      = 43200;  //redis购物车商品缓存过期时间
    private $redis       = Null;
    private $redis_ext   = '';     //redis缓存键名拼接字符串
    private $cachekey    = Null;
    private $basket      = [];     //私有空数组用于存放商品信息

    /**
     * 购物车初始化,传入用户id
     */
    public function init($user_id){
        $this->redis        = Redis::ins();       //调用redis缓存类(连接redis)
        $this->redis_ext    = '.'.config('system')['project_name_zn'];      //redis缓存键名拼接项目中文名称字符串
        $this->cachekey     = "user.cart.{$user_id}".$this->redis_ext;      //redis缓存键名拼接用户ID与项目中文名称字符串为对象用户购物车缓存键名
        $this->basket       = json_decode($this->redis->get($this->cachekey),true);     //获取对象用户的redis购物车商品缓存信息并解码为PHP数组
    }

    //添加商品 $id 商品ID  $attr_id 商品对应属性ID   $goodsName 商品名称  $number 加入数量  $price 商品对应属性单价
    public function addbasket( $id, $attr_id, $goodsName, $attr_name, $number, $price , $freight ){
        //判断对象商品是否已经存在redis购物车商品缓存内
        if( $this->isExist($id,$attr_id) ){
            //存在时增加该对象商品数量
            return $this->add($id, $attr_id ,$number);
        }
        
        //对象商品不在redis购物车商品缓存内时
        $tmp  = [];
        $tmp['goods_id']            = intval($id);        //对象商品ID
        $tmp['attr_id']             = intval($attr_id);   //对象商品对应属性ID
        $tmp['goods_name']          = $goodsName;         //对象商品名称
        $tmp['attr_name']           = $attr_name;         //对象商品名称
        $tmp['goods_number']        = intval($number);    //对象商品数量,新增的商品默认加入数量为1
        $tmp['price']               = intval($price);     //对象商品对应属性单价
        $tmp['freight']             = intval($freight);   //对象商品运费
        $tmp['subtotal']            = $tmp['goods_number'] * $price;   //对象商品总价

        $this->basket[] = $tmp;        //新的商品信息存入redis购物车商品缓存信息解码的PHP数组内,每件属性商品信息对应一个索引键值
    
        //重新将新的购物车商品信息数组编码为json字符串存入对象用户redis购物车商品缓存内
        $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));

        return 1;
    }

    //判断商品是否已经存在
    // $id 商品ID
    // $attr_id 商品属性ID
    public function isExist($id,$attr_id){
        $isExist = false;
        //当对象用户redis购物车商品缓存不为空时
        if( !empty($this->basket) ){
            foreach ($this->basket as $key=>$val){
                if( $val['goods_id'] == $id && $attr_id == $val['attr_id'] ){
                    $isExist = true;
                    break;
                }
            }
        }
        return $isExist;
    }

    //获取所有商品信息
    public function getAll(){
        return $this->basket;
    }
    
    //获取部分商品信息
    public function getPartGoods($ids)
    {
        $goods = [];
        foreach ($ids as $v) {
            foreach ($this->basket as $k => $val) {
                if ($val['goods_id'] == $v['goods_id'] && $val['attr_id'] == $v['attr_id']) {
                    $goods[] = $val;
                }
            }
        }
        return $goods;
    }
    
    //获取部分商品总数
    public function getPartGoodsNum($ids)
    {
        $number = '';
        foreach ($ids as $v) {
            foreach ($this->basket as $k => $val) {
                if ($val['goods_id'] == $v['goods_id'] && $val['attr_id'] == $v['attr_id']) {
                    $number += $val['goods_number'];
                }
            }
        }
        return $number;
    }

    /*添加商品
    * @param $id商品id
    * @param $number 添加的数量 默认为1
    * @param $type 1为在原有商品数上添加 总商品数= 当前数 + 历史数,2为总商品数 默认为 1
    */
    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=>$val){
                if( $val['goods_id'] == $id && $val['attr_id'] == $attr_id){
                    $val['goods_number'] = $val['goods_number']+$number;     //购物车存在该商品时增加该商品数量
                    $val['subtotal'] = $val['goods_number']*$val['price'];   //购物车存在该商品时重新计算该件商品总价
                    $this->basket[$key] = $val;                              //购物车存在该商品时重新将新的商品信息放入该商品的redis缓存信息内($key即为该商品的redis缓存键值)
                    $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket)); //购物车存在该商品时更新该商品的redis缓存信息
                    $goods_number = $val['goods_number'];                    //商品加入成功将商品数量赋值变量返回
                    break;
                }
            }
        }
        return $goods_number; //返回商品数量
    }

    //减一商品
    public function reduce($id, $attr_id ,$number){
        $goods_number = 0;
        if(!empty($id) && $this->isExist($id ,$attr_id )){
            $cache_detail = $this->basket;
            foreach ($cache_detail as $key=>$val){
                if( $val['goods_id'] == $id && $val['attr_id'] == $attr_id ){
                    $val['goods_number'] = $val['goods_number']-$number;
                    $goods_number = $val['goods_number'];
                    //若为0则删除
                    if( $val['goods_number'] <= 0 ){
                        $this->dele($id ,$attr_id);
                        $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
                        $goods_number = 0;
                        break;
                    }
                    $val['subtotal'] = $val['goods_number']*$val['price'];
                    $this->basket[$key] = $val;
                    $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
                    break;
                }
            }
        }
        return $goods_number;
    }

    //删除商品
    public function dele($ids){
        if(is_array($ids)){
            foreach ($ids as $v){
                foreach ($this->basket as $k=>$val) {
                    if( $val['goods_id'] == $v['goods_id'] && $val['attr_id'] == $v['attr_id'] ){
                        array_splice($this->basket,$k,1);
                    }
                }
            }
        }else{
            foreach ($this->basket as $k=>$val) {
                if( $val['goods_id'] == $ids){
                    //unset(self::$basket[$k]);
                    array_splice($this->basket,$k,1);
                }
            }
        }
        $this->redis->setex($this->cachekey,$this->expire,json_encode($this->basket));
        return true;
    }

    //清空购物车
    public function emptyCart(){
        return $this->redis->del($this->cachekey);
    }


    //部分商品总价(包含商品运费) $type不为0时商品总价与商品总运费作为关联数组返回
    public function getTotalPrices($ids,$type=0)
    {
        $totalPrice = 0;
        $goods_freight    = [];
        $freight    = 0;
        foreach ($ids as $v) {
            foreach ($this->basket as $k => $val) {
                if ($val['goods_id'] == $v['goods_id'] && $val['attr_id'] == $v['attr_id']) {
                    $totalPrice += $val['subtotal'];
                    $goods_freight[$v['goods_id']]   = $val['freight'];  //获取不同商品的运费
                }
            }
        }
        
        //相同商品不同属性只收取一次运费
        foreach ( $goods_freight as $value ){
            $freight += $value;
        }
        if ($type == 0){
            return $totalPrice+$freight;  //总价=商品总价+商品总运费
        }else{
            return ['total_price'=>$totalPrice,'freight'=>$freight];  //商品总价与商品总运费
        }
    }
    

    
    //编辑某商品数量
    public function edit($id, $attr_id, $number)
    {
        if (!empty($id) && $this->isExist($id, $attr_id) && $number > 0) {
            $cache_detail = $this->basket;
            foreach ($cache_detail as $key => $val) {
                if ($val['goods_id'] == $id && $val['attr_id'] == $attr_id) {
                    $val['goods_number'] = intval($number);
                    $val['subtotal'] = $val['goods_number'] * $val['price'];
                    $this->basket[$key] = $val;
                    return $this->redis->setex($this->cachekey, $this->expire, json_encode($this->basket));
                }
            }
        }
    }

}

 

上一篇:THINKPHP5 如何开发API以及改变输出数据类型,以及比较好用的测试接口的插件(postman)


下一篇:thinkphp5的生命周期