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+Redis单例型购物车的更多相关文章
- Redis 单例、主从模式、sentinel 以及集群的配置方式及优缺点对比(转)
摘要: redis作为一种NoSql数据库,其提供了一种高效的缓存方案,本文则主要对其单例,主从模式,sentinel以及集群的配置方式进行说明,对比其优缺点,阐述redis作为一种缓存框架的高可用性 ...
- Redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比
https://my.oschina.net/zhangxufeng/blog/905611
- php单例型(singleton pattern)
搞定,吃饭 <?php /* The purpose of singleton pattern is to restrict instantiation of class to a single ...
- spring bean单例注入与用单例模式通过class.getinstance()区别?
1.action的某个方法中,用以下代码获得redis单例实例 RedisDelegate redisDelegate = RedisDelegate.getInstance(); redisDele ...
- 初探Java设计模式1:创建型模式(工厂,单例等)
Java 设计模式 一直想写一篇介绍设计模式的文章,让读者可以很快看完,而且一看就懂,看懂就会用,同时不会将各个模式搞混.自认为本文还是写得不错的,花了不少心思来写这文章和做图,力求让读者真的能看着简 ...
- Spring + Jedis集成Redis(单例redis数据库)
这几天没事,就把之前学习的redis代码整理一遍,废话不多说,上步骤. 1.pom.xml引入资源: <dependency> <groupId>org.springframe ...
- 002-创建型-03-单例模式(Singleton)【7种】、spring单例及原理
一.概述 保证一个类仅有一个实例,并提供一个全局访问点 私有构造器.线程安全.延迟加载.序列化和反序列化安全.反射攻击 1.1.适用场景 1.在多个线程之间,比如servlet环境,共享同一个资源或者 ...
- ios oc 和 swfit 用dispatch_once 创建单例
网上已经有方法了,我这里就是抄了下,原文链接 http://bj007.blog.51cto.com/1701577/649413 http://blog.csdn.net/u010124617/ar ...
- php 设计模式 - 单例
概述: 作为对象的创建模式,单例确保某一个内在系统中只存在一个实例,它不可以创建副本. 克隆函数(__clone )以及构造函数(__construct )必须声明为私用, 防止外部程序 创建一个新类 ...
随机推荐
- 修复wordpress插件编辑器漏洞
具体方法,将下面的代码添加到您的配置文件 wp-config.php中: define( 'DISALLOW_FILE_EDIT', true ); 以此关闭插件编辑器功能,一切就这么简单,漏洞也就不 ...
- 整理Py小demo
from email.mime.text import MIMEText # 第一个参数就是邮件正文,第二个参数是MIME的subtype, # 传入'plain'表示纯文本,最终的MIME就是'te ...
- 移植开源QT软件-SameGame
前言: QML是一种描述性的脚本语言,文件格式以.qml结尾.语法格式非常像CSS(参考后文具体例子),但又支持javascript形式的编程控制.我个人认为它结合了QtDesigner UI和QtS ...
- 图像压缩Vs.压缩感知
压缩感知科普文两则: 原文链接:http://www.cvchina.info/2010/06/08/compressed-sensing-2/ 这几天由于happyharry的辛勤劳动,大伙纷纷表示 ...
- 编写可维护的javascript阅读笔记
格式 变量 变量命名, 采取小驼峰大小写 变量使用名词, 函数前缀为动词 局部变量应统一定义在函数的最上面, 而不是散落在函数的任意角落. 赋初始值的定义在未赋初始值的变量的上面. 我个人建议不使用单 ...
- ReactiveX Operators
This documentation groups information about the various operators and examples of their usage into t ...
- Spring依赖注入:@Autowired,@Resource和@Inject区别与实现原理
一.spring依赖注入使用方式 @Autowired是spring框架提供的实现依赖注入的注解,主要支持在set方法,field,构造函数中完成bean注入,注入方式为通过类型查找bean,即byT ...
- POI操作Excel的三种Workbook的发展和区别
POI的一些使用方法: 创建流程:(上级为下级的载体) 1.创建Workbook(工作薄): 2.创建Sheet(表单,可以创建多个): 3.创建Row(行): 4.创建Cell(单元格) 接下来分别 ...
- 路飞学城Python-Day53
01-jquery的介绍 JS在做项目或者是实现功能的时候,用JS去操作DOM元素非常复杂,代码量大,重复性代码也多 多个元素使用for循环遍历也是非常麻烦的,对于JS使用来说加大了难度 jQuery ...
- BZOJ 3878 [AHOI&JSOI2014]奇怪的计算器 (线段树)
题面:BZOJ传送门 洛谷传送门 线段树好题 题目保证$a$一定是正整数,容易发现计算结果是单调的 我们把询问离线,并按照从小到大排序 某次操作可能导致某些位置达到边界$L/R$ 根据单调性的结论 这 ...