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 )必须声明为私用, 防止外部程序 创建一个新类 ...
随机推荐
- 如何在在页面中清除一个已知的cookie?
前些天在写一个项目的时候,使用cookie来存储一些用户数据,在用户登出时需要清理以往的数据,对于一个初学者来说,我需要学习如何清除一个已知的cookie. 首先,引入两个js文件: 1.jquery ...
- NFS 开机自动挂载共享目录
开机自动挂载: 如果服务端或客户端的服务器重启之后需要手动挂载,我们可以加入到开机自动挂载 在服务端/客户端的/etc/fstab里添加 192.168.22.204:/opt/filestore ...
- vuejs开发H5页面总结
最近参与了APP内嵌H5页面的开发,这次使用vuejs替代了jQuery,仅仅把vuejs当做一个库来使用,效率提高之外代码可读性更强,在此分享一下自己的一些开发中总结的经验. 关于布局方案 当拿到设 ...
- hdu3416 Marriage Match IV 最短路+ 最大流
此题的大意:给定一幅有向图,求起点到终点(都是固定的)的不同的最短路有多少条.不同的最短路是说不能有相同的边,顶点可以重复.并且图含有平行边. 看了题以后,就想到暴力,但是暴力往往是不可取的.(暴力的 ...
- hdu1317 XYZZY Floyd + Bellman_Ford
这题,我在学搜索的时候做过.不过好像不叫这名字. 1.先用Floyd算法判断图的连通性.如果1与n是不连通的,输出hopeless. 2.用Bellman_Ford算法判断是否有正圈,如果某点有正圈, ...
- jq+mui 阻止事件冒泡
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...
- Ruby. Vs . Python
前言:从语言的本质上来分析,我对Ruby持反对态度,毕竟语言是为了交流,在表达的效率层面为了正确性必须适当放弃复杂性.且有句老话说的好,Ruby In Rails 才是语言,而Ruby只是这个语言的工 ...
- Linux 中文件名颜色所代表的属性
1. 白色:表示一般文件 2. 蓝色:表示目录 3. 绿色:表示可执行的文件或程序 4. 浅蓝色:表示链接文件 5. 黄色:表示设备文件 6. 灰色:表示其他类型文件 7. 红色:表示压缩文件或者包文 ...
- 主从同步工作过程?(binlog日志)
在从数据库服务器的/var/lib/mysql/master.info 记录连接主数据库服务器信息文件mail-relay-bin.XXXXXX 中继日志文件(记录SQL)mail-relay ...
- 路飞学城Python-Day137
django项目二 个人博客系统 github地址:https://github.com/pandaboy1123/cnblog