Completed
Push — 6.0 ( d0be69...b4e136 )
by liu
02:34
created

Driver::getCacheKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
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;
14
15
use Psr\SimpleCache\CacheInterface;
16
use think\Container;
17
use think\exception\InvalidArgumentException;
18
19
/**
20
 * 缓存基础类
21
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
22
abstract class Driver implements CacheInterface
23
{
24
    /**
25
     * 驱动句柄
26
     * @var object
27
     */
28
    protected $handler = null;
29
30
    /**
31
     * 缓存读取次数
32
     * @var integer
33
     */
34
    protected $readTimes = 0;
35
36
    /**
37
     * 缓存写入次数
38
     * @var integer
39
     */
40
    protected $writeTimes = 0;
41
42
    /**
43
     * 缓存参数
44
     * @var array
45
     */
46
    protected $options = [];
47
48
    /**
49
     * 缓存标签
50
     * @var array
51
     */
52
    protected $tag = [];
53
54
    /**
55
     * 获取有效期
56
     * @access protected
57
     * @param  integer|\DateTimeInterface $expire 有效期
58
     * @return int
59
     */
60
    protected function getExpireTime($expire): int
61
    {
62
        if ($expire instanceof \DateTimeInterface) {
63
            $expire = $expire->getTimestamp() - time();
64
        }
65
66
        return (int) $expire;
67
    }
68
69
    /**
70
     * 获取实际的缓存标识
71
     * @access public
72
     * @param  string $name 缓存名
73
     * @return string
74
     */
75
    public function getCacheKey(string $name): string
76
    {
77
        return $this->options['prefix'] . $name;
78
    }
79
80
    /**
81
     * 读取缓存并删除
82
     * @access public
83
     * @param  string $name 缓存变量名
84
     * @return mixed
85
     */
86
    public function pull(string $name)
87
    {
88
        $result = $this->get($name, false);
89
90
        if ($result) {
91
            $this->delete($name);
92
            return $result;
93
        }
94
    }
95
96
    /**
97
     * 追加(数组)缓存
98
     * @access public
99
     * @param  string $name 缓存变量名
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
100
     * @param  mixed  $value  存储数据
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
101
     * @return void
102
     */
103
    public function push(string $name, $value): void
104
    {
105
        $item = $this->get($name, []);
106
107
        if (!is_array($item)) {
108
            throw new InvalidArgumentException('only array cache can be push');
109
        }
110
111
        $item[] = $value;
112
113
        if (count($item) > 1000) {
114
            array_shift($item);
115
        }
116
117
        $item = array_unique($item);
118
119
        $this->set($name, $item);
120
    }
121
122
    /**
123
     * 如果不存在则写入缓存
124
     * @access public
125
     * @param  string $name 缓存变量名
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
126
     * @param  mixed  $value  存储数据
127
     * @param  int    $expire  有效时间 0为永久
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
128
     * @return mixed
129
     */
130
    public function remember(string $name, $value, $expire = null)
131
    {
132
        if ($this->has($name)) {
133
            return $this->get($name);
134
        }
135
136
        $time = time();
137
138
        while ($time + 5 > time() && $this->has($name . '_lock')) {
139
            // 存在锁定则等待
140
            usleep(200000);
141
        }
142
143
        try {
144
            // 锁定
145
            $this->set($name . '_lock', true);
146
147
            if ($value instanceof \Closure) {
148
                // 获取缓存数据
149
                $value = Container::getInstance()->invokeFunction($value);
150
            }
151
152
            // 缓存数据
153
            $this->set($name, $value, $expire);
154
155
            // 解锁
156
            $this->delete($name . '_lock');
157
        } catch (\Exception | \throwable $e) {
158
            $this->delete($name . '_lock');
159
            throw $e;
160
        }
161
162
        return $value;
163
    }
164
165
    /**
166
     * 缓存标签
167
     * @access public
168
     * @param  string $name 标签名
169
     * @return $this
170
     */
171
    public function tag(string $name)
172
    {
173
        if (!isset($this->tag[$name])) {
174
            $key = $this->getTagKey($name);
175
176
            $this->tag[$name] = new TagSet($key, $this);
177
        }
178
179
        return $this->tag[$name];
180
    }
181
182
    /**
183
     * 获取标签包含的缓存标识
184
     * @access public
185
     * @param  string $tag 标签标识
186
     * @return array
187
     */
188
    public function getTagItems(string $tag): array
189
    {
190
        return $this->get($tag, []);
191
    }
192
193
    /**
194
     * 获取实际标签名
195
     * @access protected
196
     * @param  string $tag 标签名
197
     * @return string
198
     */
199
    protected function getTagKey(string $tag): string
200
    {
201
        return $this->options['tag_prefix'] . md5($tag);
202
    }
203
204
    /**
205
     * 序列化数据
206
     * @access protected
207
     * @param  mixed $data 缓存数据
208
     * @return string
209
     */
210
    protected function serialize($data): string
211
    {
212
        $serialize = $this->options['serialize'][0] ?? '\think\App::serialize';
213
214
        return $serialize($data);
215
    }
216
217
    /**
218
     * 反序列化数据
219
     * @access protected
220
     * @param  string $data 缓存数据
221
     * @return mixed
222
     */
223
    protected function unserialize(string $data)
224
    {
225
        $unserialize = $this->options['serialize'][1] ?? '\think\App::unserialize';
226
227
        return $unserialize($data);
228
    }
229
230
    /**
231
     * 返回句柄对象,可执行其它高级方法
232
     *
233
     * @access public
234
     * @return object
235
     */
236
    public function handler()
237
    {
238
        return $this->handler;
239
    }
240
241
    /**
242
     * 返回缓存读取次数
243
     * @access public
244
     * @return int
245
     */
246
    public function getReadTimes(): int
247
    {
248
        return $this->readTimes;
249
    }
250
251
    /**
252
     * 返回缓存写入次数
253
     * @access public
254
     * @return int
255
     */
256
    public function getWriteTimes(): int
257
    {
258
        return $this->writeTimes;
259
    }
260
261
    /**
262
     * 读取缓存
263
     * @access public
264
     * @param  iterable $keys 缓存变量名
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
265
     * @param  mixed    $default 默认值
266
     * @return iterable
267
     * @throws InvalidArgumentException
268
     */
269
    public function getMultiple($keys, $default = null): iterable
270
    {
271
        $result = [];
272
273
        foreach ($keys as $key) {
274
            $result[$key] = $this->get($key, $default);
275
        }
276
277
        return $result;
278
    }
279
280
    /**
281
     * 写入缓存
282
     * @access public
283
     * @param  iterable               $values 缓存数据
284
     * @param  null|int|\DateInterval $ttl    有效时间 0为永久
285
     * @return bool
286
     */
287
    public function setMultiple($values, $ttl = null): bool
288
    {
289
        foreach ($values as $key => $val) {
290
            $result = $this->set($key, $val, $ttl);
291
292
            if (false === $result) {
293
                return false;
294
            }
295
        }
296
297
        return true;
298
    }
299
300
    /**
301
     * 删除缓存
302
     * @access public
303
     * @param iterable $keys 缓存变量名
1 ignored issue
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
304
     * @return bool
305
     * @throws InvalidArgumentException
306
     */
307
    public function deleteMultiple($keys): bool
308
    {
309
        foreach ($keys as $key) {
310
            $result = $this->delete($key);
311
312
            if (false === $result) {
313
                return false;
314
            }
315
        }
316
317
        return true;
318
    }
319
320
    public function __call($method, $args)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __call()
Loading history...
321
    {
322
        return call_user_func_array([$this->handler, $method], $args);
323
    }
324
}
325