1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Memcached Store |
4
|
|
|
* |
5
|
|
|
* @package SugiPHP.Cache |
6
|
|
|
* @author Plamen Popov <[email protected]> |
7
|
|
|
* @license http://opensource.org/licenses/mit-license.php (MIT License) |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace SugiPHP\Cache; |
11
|
|
|
|
12
|
|
|
use Memcached; |
13
|
|
|
|
14
|
|
|
class MemcachedStore implements StoreInterface, IncrementorInterface |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* Memcached instance |
18
|
|
|
*/ |
19
|
|
|
protected $memcached; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Fix bug in memcached PHP module |
23
|
|
|
* @see https://bugs.php.net/bug.php?id=51434 |
24
|
|
|
* @var boolean |
25
|
|
|
*/ |
26
|
|
|
public $bug51434fix = true; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Creates a Memcached store |
30
|
|
|
* |
31
|
|
|
* @param Memcached $memcached |
32
|
|
|
*/ |
33
|
|
|
public function __construct(Memcached $memcached) |
34
|
|
|
{ |
35
|
|
|
$this->memcached = $memcached; |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Creates MemcachedStore instance |
40
|
|
|
* |
41
|
|
|
* @param array $config Server Configurations |
42
|
|
|
* |
43
|
|
|
* @return MemcachedStore |
44
|
|
|
*/ |
45
|
|
|
public static function factory(array $config = array()) |
46
|
|
|
{ |
47
|
|
|
$memcached = new Memcached(); |
48
|
|
|
|
49
|
|
|
// empty config |
50
|
|
|
if (empty($config)) { |
51
|
|
|
$host = "127.0.0.1"; |
52
|
|
|
$port = 11211; |
53
|
|
|
|
54
|
|
|
$memcached->addServer($host, $port); |
55
|
|
|
} elseif (empty($config[0])) { |
56
|
|
|
// only one server |
57
|
|
|
$host = empty($config["host"]) ? "127.0.0.1" : $config["host"]; |
58
|
|
|
$port = empty($config["port"]) ? 11211 : $config["port"]; |
59
|
|
|
$weight = empty($config["weight"]) ? 1 : $config["weight"]; |
60
|
|
|
$memcached->addServer($host, $port, $weight); |
61
|
|
|
} else { |
62
|
|
|
// multiple servers |
63
|
|
|
$memcached->addServers($config); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
// The code using a store should work no matter if the store is running or not |
67
|
|
|
// Check is the memcache store is working with checkRunning() method |
68
|
|
|
return new MemcachedStore($memcached); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* {@inheritdoc} |
73
|
|
|
*/ |
74
|
|
|
public function add($key, $value, $ttl = 0) |
75
|
|
|
{ |
76
|
|
|
return $this->memcached->add($key, $value, $ttl); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* {@inheritdoc} |
81
|
|
|
*/ |
82
|
|
|
public function set($key, $value, $ttl = 0) |
83
|
|
|
{ |
84
|
|
|
return $this->memcached->set($key, $value, $ttl); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* {@inheritdoc} |
89
|
|
|
*/ |
90
|
|
View Code Duplication |
public function get($key) |
|
|
|
|
91
|
|
|
{ |
92
|
|
|
$result = $this->memcached->get($key); |
93
|
|
|
|
94
|
|
|
if (($result === false) && ($this->memcached->getResultCode() === Memcached::RES_NOTFOUND)) { |
95
|
|
|
return null; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
return $result; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* {@inheritdoc} |
103
|
|
|
*/ |
104
|
|
View Code Duplication |
public function has($key) |
|
|
|
|
105
|
|
|
{ |
106
|
|
|
$result = $this->memcached->get($key); |
107
|
|
|
if (($result === false) && ($this->memcached->getResultCode() === Memcached::RES_NOTFOUND)) { |
108
|
|
|
return false; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
return true; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* {@inheritdoc} |
116
|
|
|
*/ |
117
|
|
|
public function delete($key) |
118
|
|
|
{ |
119
|
|
|
$this->memcached->delete($key); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* {@inheritdoc} |
124
|
|
|
*/ |
125
|
|
|
public function flush() |
126
|
|
|
{ |
127
|
|
|
$this->memcached->flush(); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* {@inheritdoc} |
132
|
|
|
*/ |
133
|
|
View Code Duplication |
public function inc($key, $step = 1) |
|
|
|
|
134
|
|
|
{ |
135
|
|
|
// due to a bug in memcached PHP module |
136
|
|
|
// https://bugs.php.net/bug.php?id=51434 |
137
|
|
|
// we'll check if the $key has a non numeric value |
138
|
|
|
if ($this->bug51434fix) { |
139
|
|
|
$value = $this->get($key); |
140
|
|
|
if (is_null($value) || !is_numeric($value)) { |
141
|
|
|
return false; |
142
|
|
|
} |
143
|
|
|
} |
144
|
|
|
$val = $this->memcached->increment($key, $step); |
145
|
|
|
|
146
|
|
|
// on some servers it will return 0 instead of FALSE |
147
|
|
|
return ($val) ? $val : false; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* {@inheritdoc} |
152
|
|
|
*/ |
153
|
|
View Code Duplication |
public function dec($key, $step = 1) |
|
|
|
|
154
|
|
|
{ |
155
|
|
|
// due to a bug in memcached PHP module |
156
|
|
|
// https://bugs.php.net/bug.php?id=51434 |
157
|
|
|
// we'll check if the $key has a non numeric value |
158
|
|
|
if ($this->bug51434fix) { |
159
|
|
|
$value = $this->get($key); |
160
|
|
|
if (is_null($value) || !is_numeric($value)) { |
161
|
|
|
return false; |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
$val = $this->memcached->decrement($key, $step); |
165
|
|
|
|
166
|
|
|
// on some servers it will return 0 instead of FALSE |
167
|
|
|
return ($val) ? $val : false; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Checks is the memcache server is running |
172
|
|
|
* |
173
|
|
|
* @return boolean |
174
|
|
|
*/ |
175
|
|
|
public function checkRunning() |
176
|
|
|
{ |
177
|
|
|
$servers = $this->memcached->getVersion(); |
178
|
|
|
|
179
|
|
|
// this happens when no servers were added |
180
|
|
|
if (!$servers) { |
181
|
|
|
return false; |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
// at least one server should be running |
185
|
|
|
foreach ($servers as $server) { |
186
|
|
|
if ($server != "255.255.255") { |
187
|
|
|
return true; |
188
|
|
|
} |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
return false; |
192
|
|
|
} |
193
|
|
|
} |
194
|
|
|
|
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.