CacheCart.php
7.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<?php
namespace addons\litestore\model;
use think\Cache;
/**
* 购物车管理
* Class Cart
*/
class CacheCart
{
/* @var string $error 错误信息 */
public $error = '';
/* @var int $user_id 用户id */
private $user_id;
/* @var array $cart 购物车列表 */
private $cart = [];
/* @var bool $clear 是否清空购物车 */
private $clear = false;
/**
* 构造方法
* Cart constructor.
* @param $user_id
*/
public function __construct($user_id)
{
$this->user_id = $user_id;
$this->cart = Cache::get('cart_' . $this->user_id) ?: [];
}
/**
* 购物车列表
*/
public function getList($user_id)
{
// 商品列表
$goodsList = [];
$goodsIds = array_unique(array_column($this->cart, 'goods_id'));
foreach ((new Wxlitestoregoods)->getListByIds($goodsIds) as $goods) {
$goodsList[$goods['goods_id']] = $goods;
}
// 当前用户收货城市id
$defaultcity = Litestoreadress::getdefault($user_id);
$cityId = $defaultcity ? $defaultcity['city_id'] : null;
// 是否存在收货地址
$exist_address = $defaultcity;
// 商品是否在配送范围
$intraRegion = true;
// 购物车商品列表
$cartList = [];
foreach ($this->cart as $key => $cart) {
// 判断商品不存在则自动删除
if (!isset($goodsList[$cart['goods_id']])) {
$this->delete($cart['goods_id'], $cart['goods_sku_id']);
continue;
}
/* @var Goods $goods */
$goods = $goodsList[$cart['goods_id']];
// 商品sku信息
$goods['goods_sku_id'] = $cart['goods_sku_id'];
// 商品sku不存在则自动删除
if (!$goods['goods_sku'] = $goods->getGoodsSku($cart['goods_sku_id'])) {
$this->delete($cart['goods_id'], $cart['goods_sku_id']);
continue;
}
$goods['show_error'] = 0;
// 判断商品是否下架
if ($goods['goods_status']!== '10') {
$goods['show_error'] = 1;
$goods['show_error_text'] = '已下架';
$this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 已下架');
}
// 判断商品库存
if ($cart['goods_num'] > $goods['goods_sku']['stock_num']) {
$goods['show_error'] = 2;
$goods['show_error_text'] = '库存不足';
$this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 库存不足');
}
// 商品单价
$goods['goods_price'] = $goods['goods_sku']['goods_price'];
// 商品总价
$goods['total_num'] = $cart['goods_num'];
$goods['total_price'] = $total_price = bcmul($goods['goods_price'], $cart['goods_num'], 2);
// 商品总重量
$goods['goods_total_weight'] = bcmul($goods['goods_sku']['goods_weight'], $cart['goods_num'], 2);
// 验证用户收货地址是否存在运费规则中
if ($intraRegion = $goods['freight']->checkAddress($cityId)) {
$goods['express_price'] = $goods['freight']->calcTotalFee(
$cart['goods_num'], $goods['goods_total_weight'], $cityId);
} else {
//$goods['show_error'] = 3;
//$goods['show_error_text'] = '收货区域无法配送';
$exist_address && $this->setError("很抱歉,您的收货地址不在商品 [{$goods['goods_name']}] 的配送范围内");
}
$cartList[] = $goods->toArray();
}
// 商品总金额
$orderTotalPrice = array_sum(array_column($cartList, 'total_price'));
// 所有商品的运费金额
$allExpressPrice = array_column($cartList, 'express_price');
// 订单总运费金额
$expressPrice = $allExpressPrice ? Litestorefreight::freightRule($allExpressPrice) : 0.00;
return [
'goods_list' => $cartList, // 商品列表
'order_total_num' => $this->getTotalNum(), // 商品总数量
'order_total_price' => round($orderTotalPrice, 2), // 商品总金额 (不含运费)
'order_pay_price' => bcadd($orderTotalPrice, $expressPrice, 2), // 实际支付金额
'address' => $defaultcity, // 默认地址
'exist_address' => $exist_address, // 是否存在收货地址
'express_price' => $expressPrice, // 配送费用
'intra_region' => $intraRegion, // 当前用户收货城市是否存在配送规则中
'has_error' => $this->hasError(),
'error_msg' => $this->getError(),
];
}
/**
* 添加购物车
* @param $goods_id
* @param $goods_num
* @param $goods_sku_id
* @return bool
* @throws \think\exception\DbException
*/
public function add($goods_id, $goods_num, $goods_sku_id)
{
// 购物车商品索引
$index = $goods_id . '_' . $goods_sku_id;
// 商品信息
$goods = Wxlitestoregoods::detail($goods_id);
// 商品sku信息
$goods['goods_sku'] = $goods->getGoodsSku($goods_sku_id);
// 判断商品是否下架
if ($goods['goods_status'] !== '10') {
$this->setError('很抱歉,该商品已下架');
return false;
}
// 判断商品库存
$cartGoodsNum = $goods_num + (isset($this->cart[$index]) ? $this->cart[$index]['goods_num'] : 0);
if ($cartGoodsNum > $goods['goods_sku']['stock_num']) {
$this->setError('很抱歉,商品库存不足');
return false;
}
$create_time = time();
$data = compact('goods_id', 'goods_num', 'goods_sku_id', 'create_time');
if (empty($this->cart)) {
$this->cart[$index] = $data;
return true;
}
isset($this->cart[$index]) ? $this->cart[$index]['goods_num'] = $cartGoodsNum : $this->cart[$index] = $data;
return true;
}
/**
* 减少购物车中某商品数量
* @param $goods_id
* @param $goods_sku_id
*/
public function sub($goods_id, $goods_sku_id)
{
$index = $goods_id . '_' . $goods_sku_id;
$this->cart[$index]['goods_num'] > 1 && $this->cart[$index]['goods_num']--;
}
/**
* 删除购物车中指定商品
* @param $goods_id
* @param $goods_sku_id
*/
public function delete($goods_id, $goods_sku_id)
{
$index = $goods_id . '_' . $goods_sku_id;
unset($this->cart[$index]);
}
/**
* 获取当前用户购物车商品总数量
* @return int
*/
public function getTotalNum()
{
return array_sum(array_column($this->cart, 'goods_num'));
}
/**
* 析构方法
* 将cart数据保存到缓存文件
*/
public function __destruct()
{
$this->clear !== true && Cache::set('cart_' . $this->user_id, $this->cart, 86400 * 15);
}
/**
* 清空当前用户购物车
*/
public function clearAll()
{
$this->clear = true;
Cache::rm('cart_' . $this->user_id);
}
/**
* 设置错误信息
* @param $error
*/
private function setError($error)
{
empty($this->error) && $this->error = $error;
}
/**
* 是否存在错误
* @return bool
*/
private function hasError()
{
return !empty($this->error);
}
/**
* 获取错误信息
* @return string
*/
public function getError()
{
return $this->error;
}
}