]>
Commit | Line | Data |
---|---|---|
ed9b544e | 1 | <?php |
2 | /******************************************************************************* | |
3 | * Redis PHP Bindings - http://code.google.com/p/redis/ | |
4 | * | |
5 | * Copyright 2009 Ludovico Magnocavallo | |
8d03032a | 6 | * Copyright 2009 Salvatore Sanfilippo (ported it to PHP5, fixed some bug) |
ed9b544e | 7 | * Released under the same license as Redis. |
8 | * | |
9 | * Version: 0.1 | |
10 | * | |
11 | * $Revision: 139 $ | |
12 | * $Date: 2009-03-15 22:59:40 +0100 (Dom, 15 Mar 2009) $ | |
13 | * | |
14 | ******************************************************************************/ | |
15 | ||
16 | ||
17 | class Redis { | |
8d03032a | 18 | public $server; |
19 | public $port; | |
20 | private $_sock; | |
21 | ||
22 | public function __construct($host='localhost', $port=6379) { | |
ed9b544e | 23 | $this->host = $host; |
24 | $this->port = $port; | |
25 | } | |
26 | ||
8d03032a | 27 | public function connect() { |
28 | if ($this->_sock) return; | |
ed9b544e | 29 | if ($sock = fsockopen($this->host, $this->port, $errno, $errstr)) { |
30 | $this->_sock = $sock; | |
31 | return; | |
32 | } | |
33 | $msg = "Cannot open socket to {$this->host}:{$this->port}"; | |
34 | if ($errno || $errmsg) | |
8d03032a | 35 | $msg .= "," . ($errno ? " error $errno" : "") . |
36 | ($errmsg ? " $errmsg" : ""); | |
ed9b544e | 37 | trigger_error("$msg.", E_USER_ERROR); |
38 | } | |
39 | ||
8d03032a | 40 | public function disconnect() { |
41 | if ($this->_sock) @fclose($this->_sock); | |
ed9b544e | 42 | $this->_sock = null; |
43 | } | |
44 | ||
8d03032a | 45 | public function ping() { |
ed9b544e | 46 | $this->connect(); |
8d03032a | 47 | $this->write("PING\r\n"); |
bb7dcc1e | 48 | return $this->get_response(); |
ed9b544e | 49 | } |
50 | ||
8d03032a | 51 | public function do_echo($s) { |
ed9b544e | 52 | $this->connect(); |
8d03032a | 53 | $this->write("ECHO " . strlen($s) . "\r\n$s\r\n"); |
54 | return $this->get_response(); | |
ed9b544e | 55 | } |
56 | ||
8d03032a | 57 | public function set($name, $value, $preserve=false) { |
ed9b544e | 58 | $this->connect(); |
8d03032a | 59 | $this->write( |
ed9b544e | 60 | ($preserve ? 'SETNX' : 'SET') . |
61 | " $name " . strlen($value) . "\r\n$value\r\n" | |
62 | ); | |
bb7dcc1e | 63 | return $this->get_response(); |
ed9b544e | 64 | } |
65 | ||
8d03032a | 66 | public function get($name) { |
ed9b544e | 67 | $this->connect(); |
8d03032a | 68 | $this->write("GET $name\r\n"); |
69 | return $this->get_response(); | |
ed9b544e | 70 | } |
71 | ||
8d03032a | 72 | public function incr($name, $amount=1) { |
ed9b544e | 73 | $this->connect(); |
74 | if ($amount == 1) | |
8d03032a | 75 | $this->write("INCR $name\r\n"); |
ed9b544e | 76 | else |
8d03032a | 77 | $this->write("INCRBY $name $amount\r\n"); |
bb7dcc1e | 78 | return $this->get_response(); |
ed9b544e | 79 | } |
80 | ||
8d03032a | 81 | public function decr($name, $amount=1) { |
ed9b544e | 82 | $this->connect(); |
83 | if ($amount == 1) | |
8d03032a | 84 | $this->write("DECR $name\r\n"); |
ed9b544e | 85 | else |
8d03032a | 86 | $this->write("DECRBY $name $amount\r\n"); |
bb7dcc1e | 87 | return $this->get_response(); |
ed9b544e | 88 | } |
89 | ||
8d03032a | 90 | public function exists($name) { |
ed9b544e | 91 | $this->connect(); |
8d03032a | 92 | $this->write("EXISTS $name\r\n"); |
bb7dcc1e | 93 | return $this->get_response(); |
ed9b544e | 94 | } |
95 | ||
8d03032a | 96 | public function delete($name) { |
ed9b544e | 97 | $this->connect(); |
8d03032a | 98 | $this->write("DEL $name\r\n"); |
bb7dcc1e | 99 | return $this->get_response(); |
ed9b544e | 100 | } |
101 | ||
8d03032a | 102 | public function keys($pattern) { |
ed9b544e | 103 | $this->connect(); |
8d03032a | 104 | $this->write("KEYS $pattern\r\n"); |
105 | return explode(' ', $this->get_response()); | |
ed9b544e | 106 | } |
107 | ||
8d03032a | 108 | public function randomkey() { |
ed9b544e | 109 | $this->connect(); |
8d03032a | 110 | $this->write("RANDOMKEY\r\n"); |
bb7dcc1e | 111 | return $this->get_response(); |
ed9b544e | 112 | } |
113 | ||
8d03032a | 114 | public function rename($src, $dst) { |
115 | $this->connect(); | |
116 | $this->write("RENAME $src $dst\r\n"); | |
117 | return $this->get_response(); | |
118 | } | |
119 | ||
120 | public function renamenx($src, $dst) { | |
ed9b544e | 121 | $this->connect(); |
8d03032a | 122 | $this->write("RENAMENX $src $dst\r\n"); |
bb7dcc1e | 123 | return $this->get_response(); |
ed9b544e | 124 | } |
125 | ||
8d03032a | 126 | public function expire($name, $time) { |
9a2944ac | 127 | $this->connect(); |
8d03032a | 128 | $this->write("EXPIRE $name $time\r\n"); |
9a2944ac LM |
129 | return $this->get_response(); |
130 | } | |
131 | ||
8d03032a | 132 | public function push($name, $value, $tail=true) { |
ed9b544e | 133 | // default is to append the element to the list |
134 | $this->connect(); | |
8d03032a | 135 | $this->write( |
ed9b544e | 136 | ($tail ? 'RPUSH' : 'LPUSH') . |
137 | " $name " . strlen($value) . "\r\n$value\r\n" | |
138 | ); | |
bb7dcc1e | 139 | return $this->get_response(); |
ed9b544e | 140 | } |
8d03032a | 141 | |
142 | public function lpush($name, $value) { | |
143 | return $this->push($name, $value, false); | |
144 | } | |
145 | ||
146 | public function rpush($name, $value) { | |
147 | return $this->push($name, $value, true); | |
148 | } | |
149 | ||
150 | public function ltrim($name, $start, $end) { | |
ed9b544e | 151 | $this->connect(); |
8d03032a | 152 | $this->write("LTRIM $name $start $end\r\n"); |
bb7dcc1e | 153 | return $this->get_response(); |
ed9b544e | 154 | } |
155 | ||
8d03032a | 156 | public function lindex($name, $index) { |
ed9b544e | 157 | $this->connect(); |
8d03032a | 158 | $this->write("LINDEX $name $index\r\n"); |
159 | return $this->get_response(); | |
ed9b544e | 160 | } |
161 | ||
8d03032a | 162 | public function pop($name, $tail=true) { |
ed9b544e | 163 | $this->connect(); |
8d03032a | 164 | $this->write( |
ed9b544e | 165 | ($tail ? 'RPOP' : 'LPOP') . |
166 | " $name\r\n" | |
167 | ); | |
8d03032a | 168 | return $this->get_response(); |
169 | } | |
170 | ||
171 | public function lpop($name, $value) { | |
172 | return $this->pop($name, $value, false); | |
173 | } | |
174 | ||
175 | public function rpop($name, $value) { | |
176 | return $this->pop($name, $value, true); | |
ed9b544e | 177 | } |
178 | ||
8d03032a | 179 | public function llen($name) { |
ed9b544e | 180 | $this->connect(); |
8d03032a | 181 | $this->write("LLEN $name\r\n"); |
bb7dcc1e | 182 | return $this->get_response(); |
ed9b544e | 183 | } |
184 | ||
8d03032a | 185 | public function lrange($name, $start, $end) { |
ed9b544e | 186 | $this->connect(); |
8d03032a | 187 | $this->write("LRANGE $name $start $end\r\n"); |
bb7dcc1e | 188 | return $this->get_response(); |
ed9b544e | 189 | } |
190 | ||
8d03032a | 191 | public function sort($name, $query=false) { |
ed9b544e | 192 | $this->connect(); |
8d03032a | 193 | $this->write($query == false ? "SORT $name\r\n" : "SORT $name $query\r\n"); |
bb7dcc1e | 194 | return $this->get_response(); |
ed9b544e | 195 | } |
196 | ||
8d03032a | 197 | public function lset($name, $value, $index) { |
ed9b544e | 198 | $this->connect(); |
8d03032a | 199 | $this->write("LSET $name $index " . strlen($value) . "\r\n$value\r\n"); |
bb7dcc1e | 200 | return $this->get_response(); |
ed9b544e | 201 | } |
202 | ||
8d03032a | 203 | public function sadd($name, $value) { |
ed9b544e | 204 | $this->connect(); |
8d03032a | 205 | $this->write("SADD $name " . strlen($value) . "\r\n$value\r\n"); |
bb7dcc1e | 206 | return $this->get_response(); |
ed9b544e | 207 | } |
208 | ||
8d03032a | 209 | public function srem($name, $value) { |
ed9b544e | 210 | $this->connect(); |
8d03032a | 211 | $this->write("SREM $name " . strlen($value) . "\r\n$value\r\n"); |
bb7dcc1e | 212 | return $this->get_response(); |
ed9b544e | 213 | } |
214 | ||
8d03032a | 215 | public function sismember($name, $value) { |
ed9b544e | 216 | $this->connect(); |
8d03032a | 217 | $this->write("SISMEMBER $name " . strlen($value) . "\r\n$value\r\n"); |
bb7dcc1e | 218 | return $this->get_response(); |
ed9b544e | 219 | } |
220 | ||
8d03032a | 221 | public function sinter($sets) { |
ed9b544e | 222 | $this->connect(); |
8d03032a | 223 | $this->write('SINTER ' . implode(' ', $sets) . "\r\n"); |
bb7dcc1e | 224 | return $this->get_response(); |
ed9b544e | 225 | } |
226 | ||
8d03032a | 227 | public function smembers($name) { |
ed9b544e | 228 | $this->connect(); |
8d03032a | 229 | $this->write("SMEMBERS $name\r\n"); |
bb7dcc1e | 230 | return $this->get_response(); |
ed9b544e | 231 | } |
232 | ||
8d03032a | 233 | public function scard($name) { |
ed9b544e | 234 | $this->connect(); |
8d03032a | 235 | $this->write("SCARD $name\r\n"); |
bb7dcc1e | 236 | return $this->get_response(); |
ed9b544e | 237 | } |
238 | ||
8d03032a | 239 | public function select_db($name) { |
ed9b544e | 240 | $this->connect(); |
8d03032a | 241 | $this->write("SELECT $name\r\n"); |
bb7dcc1e | 242 | return $this->get_response(); |
ed9b544e | 243 | } |
244 | ||
8d03032a | 245 | public function move($name, $db) { |
ed9b544e | 246 | $this->connect(); |
8d03032a | 247 | $this->write("MOVE $name $db\r\n"); |
bb7dcc1e | 248 | return $this->get_response(); |
ed9b544e | 249 | } |
250 | ||
8d03032a | 251 | public function save($background=false) { |
ed9b544e | 252 | $this->connect(); |
8d03032a | 253 | $this->write(($background ? "BGSAVE\r\n" : "SAVE\r\n")); |
bb7dcc1e | 254 | return $this->get_response(); |
ed9b544e | 255 | } |
256 | ||
8d03032a | 257 | public function bgsave($background=false) { |
258 | return $this->save(true); | |
259 | } | |
260 | ||
261 | public function lastsave() { | |
ed9b544e | 262 | $this->connect(); |
8d03032a | 263 | $this->write("LASTSAVE\r\n"); |
bb7dcc1e LM |
264 | return $this->get_response(); |
265 | } | |
266 | ||
8d03032a | 267 | public function flushdb($all=false) { |
bb7dcc1e | 268 | $this->connect(); |
8d03032a | 269 | $this->write($all ? "FLUSHALL\r\n" : "FLUSHDB\r\n"); |
bb7dcc1e LM |
270 | return $this->get_response(); |
271 | } | |
8d03032a | 272 | |
273 | public function flushall() { | |
274 | return $this->flush(true); | |
275 | } | |
bb7dcc1e | 276 | |
8d03032a | 277 | public function info() { |
bb7dcc1e | 278 | $this->connect(); |
8d03032a | 279 | $this->write("INFO\r\n"); |
bb7dcc1e LM |
280 | $info = array(); |
281 | $data =& $this->get_response(); | |
282 | foreach (explode("\r\n", $data) as $l) { | |
283 | if (!$l) | |
284 | continue; | |
285 | list($k, $v) = explode(':', $l, 2); | |
286 | $_v = strpos($v, '.') !== false ? (float)$v : (int)$v; | |
287 | $info[$k] = (string)$_v == $v ? $_v : $v; | |
288 | } | |
289 | return $info; | |
ed9b544e | 290 | } |
291 | ||
8d03032a | 292 | private function write($s) { |
ed9b544e | 293 | while ($s) { |
294 | $i = fwrite($this->_sock, $s); | |
bb7dcc1e | 295 | if ($i == 0) // || $i == strlen($s)) |
ed9b544e | 296 | break; |
297 | $s = substr($s, $i); | |
298 | } | |
299 | } | |
300 | ||
8d03032a | 301 | private function read($len=1024) { |
ed9b544e | 302 | if ($s = fgets($this->_sock)) |
303 | return $s; | |
304 | $this->disconnect(); | |
305 | trigger_error("Cannot read from socket.", E_USER_ERROR); | |
306 | } | |
307 | ||
8d03032a | 308 | private function get_response() { |
309 | $data = trim($this->read()); | |
bb7dcc1e LM |
310 | $c = $data[0]; |
311 | $data = substr($data, 1); | |
312 | switch ($c) { | |
313 | case '-': | |
8d03032a | 314 | trigger_error($data, E_USER_ERROR); |
bb7dcc1e LM |
315 | break; |
316 | case '+': | |
317 | return $data; | |
8d03032a | 318 | case ':': |
319 | $i = strpos($data, '.') !== false ? (int)$data : (float)$data; | |
320 | if ((string)$i != $data) | |
321 | trigger_error("Cannot convert data '$c$data' to integer", E_USER_ERROR); | |
322 | return $i; | |
323 | case '$': | |
324 | return $this->get_bulk_reply($c . $data); | |
bb7dcc1e LM |
325 | case '*': |
326 | $num = (int)$data; | |
327 | if ((string)$num != $data) | |
328 | trigger_error("Cannot convert multi-response header '$data' to integer", E_USER_ERROR); | |
329 | $result = array(); | |
330 | for ($i=0; $i<$num; $i++) | |
8d03032a | 331 | $result[] =& $this->get_response(); |
bb7dcc1e LM |
332 | return $result; |
333 | default: | |
8d03032a | 334 | trigger_error("Invalid reply type byte: '$c'"); |
ed9b544e | 335 | } |
bb7dcc1e LM |
336 | } |
337 | ||
8d03032a | 338 | private function get_bulk_reply($data=null) { |
bb7dcc1e | 339 | if ($data === null) |
8d03032a | 340 | $data = trim($this->read()); |
bb7dcc1e | 341 | if ($data == '$-1') |
ed9b544e | 342 | return null; |
bb7dcc1e LM |
343 | $c = $data[0]; |
344 | $data = substr($data, 1); | |
8d03032a | 345 | $bulklen = (int)$data; |
346 | if ((string)$bulklen != $data) | |
347 | trigger_error("Cannot convert bulk read header '$c$data' to integer", E_USER_ERROR); | |
bb7dcc1e LM |
348 | if ($c != '$') |
349 | trigger_error("Unkown response prefix for '$c$data'", E_USER_ERROR); | |
ed9b544e | 350 | $buffer = ''; |
8d03032a | 351 | while ($bulklen) { |
352 | $data = fread($this->_sock,$bulklen); | |
353 | $bulklen -= strlen($data); | |
bb7dcc1e | 354 | $buffer .= $data; |
ed9b544e | 355 | } |
8d03032a | 356 | $crlf = fread($this->_sock,2); |
357 | return $buffer; | |
ed9b544e | 358 | } |
8d03032a | 359 | } |
ed9b544e | 360 | |
975a5b6f | 361 | /* |
8d03032a | 362 | $r = new Redis(); |
975a5b6f | 363 | var_dump($r->set("foo","bar")); |
8d03032a | 364 | var_dump($r->get("foo")); |
365 | var_dump($r->info()); | |
975a5b6f | 366 | */ |
ed9b544e | 367 | |
368 | ?> |