<?php
/**
* Redis + 单例型购物车
* param $basket 存储商品信息
* param $ins 存储实例化对象
*/
namespace lib;
use redisRedis;
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));
}
}
}
}
}