-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathCache.php
More file actions
154 lines (133 loc) · 4.05 KB
/
Cache.php
File metadata and controls
154 lines (133 loc) · 4.05 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
<?php
namespace yeszao\cache;
use \InvalidArgumentException;
use \Redis;
/**
* PHP轻量级Redis缓存策略类。
*
* @author 歪麦 <galley.meng@gmail.com>
* @link https://www.awaimai.com/
*
*/
class Cache
{
/**
* Redis句柄
* @var Redis
*/
private $redis;
/**
* 正在调用的方法名称
* @var string
*/
private $class;
/**
* 配置
* @var array
*/
private $config = [
'prefix' => '',
'expire' => 3600, // 缓存过期时间
'emptyExpire' => 10 // 空值的缓存过期时间
];
/**
* 可用的Redis操作方法名
* @var array
*/
private $actions = ['cache', 'clear', 'flush'];
/**
* 构造方法
* @param Redis|null $redis
*/
public function __construct(Redis $redis = null, $config = [])
{
$this->redis = $redis;
$this->config = array_merge($this->config, $config);
}
/**
* 设置缓存时间
*
* @param $time int 单位秒
*/
public function expire($time)
{
$this->config['expire'] = $time;
}
/**
* 处理缓存方法
*
* @param $object object 对象
* @param $method string 方法名
* @param $arguments array 参数列表
* @return mixed
* @throws InvalidArgumentException 如果方法不存在,抛出异常
*/
public function get($object, $name, $arguments)
{
if ($this->redis === null) {
throw new InvalidArgumentException("未初始化Redis变量。\n");
}
$this->class = get_class($object);
if (strlen($name) < 5) {
throw new InvalidArgumentException(sprintf("Method %s->%s does not exist", $this->class, $name));
}
$method = substr($name, 0, -5);
$action = substr($name, -5);
if (!in_array($action, $this->actions, true) === false) {
throw new InvalidArgumentException(sprintf("Method %s->%s does not exist", $this->class, $method));
}
return $this->$action($object, $method, $arguments);
}
/**
* 获取某个方法返回的数据。
* 如果数据已经缓存,则直接读取缓存数据;
* 如果数据未缓存,则调用实际方法获取数据。
* 实际使用时,请在子类的注释加上`@method`注释,以便编辑器能够自动识别。
* @return mixed
* @throws InvalidArgumentException 如果方法不存在,抛出异常
*/
private function cache($object, $method, $arguments)
{
$key = $this->key($method, $arguments);
$data = $this->redis->get($key);
if ($data !== false) {
$decodeData = json_decode($data, JSON_UNESCAPED_UNICODE);
return $decodeData === null ? $data : $decodeData;
}
if (method_exists($object, $method) === false) {
throw new InvalidArgumentException(sprintf("Method %s->%s does not exist", $this->class, $method));
}
$data = call_user_func_array([$object, $method], $arguments);
$expire = empty($data) ? $this->config['emptyExpire'] : $this->config['expire'];
$this->redis->set($key, json_encode($data), $expire);
return $data;
}
/**
* 删除指定缓存,参数和原数据获取方法一样
* @return mixed
*/
private function clear($object, $method, $arguments)
{
return $this->redis->del($this->key($method, $arguments));
}
/**
* 删除指定方法的所有缓存
* @return bool
*/
private function flush($object, $method, $arguments)
{
$key = $this->key($method, '*');
$keys = $this->redis->keys($key);
return $this->redis->del($keys);
}
/**
* 生成缓存键名
* @return string
*/
private function key($method, $arguments)
{
$class = str_replace('\\', '_', $this->class);
$args = ($arguments === '*') ? '*' : md5(json_encode($arguments));
return strtolower(sprintf('%s%s:%s:%s', $this->config['prefix'], $class, $method, $args));
}
}