<?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)); } } } } }