1
|
|
|
<?php |
2
|
|
|
// +---------------------------------------------------------------------- |
3
|
|
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ] |
4
|
|
|
// +---------------------------------------------------------------------- |
5
|
|
|
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved. |
6
|
|
|
// +---------------------------------------------------------------------- |
7
|
|
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) |
8
|
|
|
// +---------------------------------------------------------------------- |
9
|
|
|
// | Author: liu21st <[email protected]> |
10
|
|
|
// +---------------------------------------------------------------------- |
11
|
|
|
declare (strict_types = 1); |
12
|
|
|
|
13
|
|
|
namespace think\cache\driver; |
14
|
|
|
|
15
|
|
|
use think\cache\Driver; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Memcache缓存类 |
19
|
|
|
*/ |
20
|
|
|
class Memcache extends Driver |
21
|
|
|
{ |
22
|
|
|
/** |
23
|
|
|
* 配置参数 |
24
|
|
|
* @var array |
25
|
|
|
*/ |
26
|
|
|
protected $options = [ |
27
|
|
|
'host' => '127.0.0.1', |
28
|
|
|
'port' => 11211, |
29
|
|
|
'expire' => 0, |
30
|
|
|
'timeout' => 0, // 超时时间(单位:毫秒) |
31
|
|
|
'persistent' => true, |
32
|
|
|
'prefix' => '', |
33
|
|
|
'tag_prefix' => 'tag:', |
34
|
|
|
'serialize' => [], |
35
|
|
|
]; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* 架构函数 |
39
|
|
|
* @access public |
40
|
|
|
* @param array $options 缓存参数 |
41
|
|
|
* @throws \BadFunctionCallException |
42
|
|
|
*/ |
43
|
|
|
public function __construct(array $options = []) |
44
|
|
|
{ |
45
|
|
|
if (!extension_loaded('memcache')) { |
46
|
|
|
throw new \BadFunctionCallException('not support: memcache'); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
if (!empty($options)) { |
50
|
|
|
$this->options = array_merge($this->options, $options); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
$this->handler = new \Memcache; |
54
|
|
|
|
55
|
|
|
// 支持集群 |
56
|
|
|
$hosts = (array) $this->options['host']; |
57
|
|
|
$ports = (array) $this->options['port']; |
58
|
|
|
|
59
|
|
|
if (empty($ports[0])) { |
60
|
|
|
$ports[0] = 11211; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
// 建立连接 |
64
|
|
|
foreach ($hosts as $i => $host) { |
65
|
|
|
$port = $ports[$i] ?? $ports[0]; |
66
|
|
|
$this->options['timeout'] > 0 ? |
67
|
|
|
$this->handler->addServer($host, (int) $port, $this->options['persistent'], 1, (int) $this->options['timeout']) : |
68
|
|
|
$this->handler->addServer($host, (int) $port, $this->options['persistent'], 1); |
69
|
|
|
} |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* 判断缓存 |
74
|
|
|
* @access public |
75
|
|
|
* @param string $name 缓存变量名 |
76
|
|
|
* @return bool |
77
|
|
|
*/ |
78
|
|
|
public function has($name): bool |
79
|
|
|
{ |
80
|
|
|
$key = $this->getCacheKey($name); |
81
|
|
|
|
82
|
|
|
return false !== $this->handler->get($key); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* 读取缓存 |
87
|
|
|
* @access public |
88
|
|
|
* @param string $name 缓存变量名 |
89
|
|
|
* @param mixed $default 默认值 |
90
|
|
|
* @return mixed |
91
|
|
|
*/ |
92
|
|
View Code Duplication |
public function get($name, $default = null) |
|
|
|
|
93
|
|
|
{ |
94
|
|
|
$this->readTimes++; |
95
|
|
|
|
96
|
|
|
$result = $this->handler->get($this->getCacheKey($name)); |
97
|
|
|
|
98
|
|
|
return false !== $result ? $this->unserialize($result) : $default; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* 写入缓存 |
103
|
|
|
* @access public |
104
|
|
|
* @param string $name 缓存变量名 |
105
|
|
|
* @param mixed $value 存储数据 |
106
|
|
|
* @param int|\DateTime $expire 有效时间(秒) |
107
|
|
|
* @return bool |
108
|
|
|
*/ |
109
|
|
View Code Duplication |
public function set($name, $value, $expire = null): bool |
|
|
|
|
110
|
|
|
{ |
111
|
|
|
$this->writeTimes++; |
112
|
|
|
|
113
|
|
|
if (is_null($expire)) { |
114
|
|
|
$expire = $this->options['expire']; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$key = $this->getCacheKey($name); |
118
|
|
|
$expire = $this->getExpireTime($expire); |
119
|
|
|
$value = $this->serialize($value); |
120
|
|
|
|
121
|
|
|
if ($this->handler->set($key, $value, 0, $expire)) { |
122
|
|
|
return true; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
return false; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* 自增缓存(针对数值缓存) |
130
|
|
|
* @access public |
131
|
|
|
* @param string $name 缓存变量名 |
132
|
|
|
* @param int $step 步长 |
133
|
|
|
* @return false|int |
134
|
|
|
*/ |
135
|
|
View Code Duplication |
public function inc(string $name, int $step = 1) |
|
|
|
|
136
|
|
|
{ |
137
|
|
|
$this->writeTimes++; |
138
|
|
|
|
139
|
|
|
$key = $this->getCacheKey($name); |
140
|
|
|
|
141
|
|
|
if ($this->handler->get($key)) { |
142
|
|
|
return $this->handler->increment($key, $step); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
return $this->handler->set($key, $step); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* 自减缓存(针对数值缓存) |
150
|
|
|
* @access public |
151
|
|
|
* @param string $name 缓存变量名 |
152
|
|
|
* @param int $step 步长 |
153
|
|
|
* @return false|int |
154
|
|
|
*/ |
155
|
|
View Code Duplication |
public function dec(string $name, int $step = 1) |
|
|
|
|
156
|
|
|
{ |
157
|
|
|
$this->writeTimes++; |
158
|
|
|
|
159
|
|
|
$key = $this->getCacheKey($name); |
160
|
|
|
$value = $this->handler->get($key) - $step; |
161
|
|
|
$res = $this->handler->set($key, $value); |
162
|
|
|
|
163
|
|
|
return !$res ? false : $value; |
|
|
|
|
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* 删除缓存 |
168
|
|
|
* @access public |
169
|
|
|
* @param string $name 缓存变量名 |
170
|
|
|
* @param bool|false $ttl |
171
|
|
|
* @return bool |
172
|
|
|
*/ |
173
|
|
View Code Duplication |
public function delete($name, $ttl = false): bool |
|
|
|
|
174
|
|
|
{ |
175
|
|
|
$this->writeTimes++; |
176
|
|
|
|
177
|
|
|
$key = $this->getCacheKey($name); |
178
|
|
|
|
179
|
|
|
return false === $ttl ? |
180
|
|
|
$this->handler->delete($key) : |
181
|
|
|
$this->handler->delete($key, $ttl); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* 清除缓存 |
186
|
|
|
* @access public |
187
|
|
|
* @return bool |
188
|
|
|
*/ |
189
|
|
|
public function clear(): bool |
190
|
|
|
{ |
191
|
|
|
$this->writeTimes++; |
192
|
|
|
|
193
|
|
|
return $this->handler->flush(); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* 删除缓存标签 |
198
|
|
|
* @access public |
199
|
|
|
* @param array $keys 缓存标识列表 |
200
|
|
|
* @return void |
201
|
|
|
*/ |
202
|
|
|
public function clearTag(array $keys): void |
203
|
|
|
{ |
204
|
|
|
foreach ($keys as $key) { |
205
|
|
|
$this->handler->delete($key); |
206
|
|
|
} |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
} |
210
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.