]> git.saurik.com Git - redis.git/blame - client-libraries/php/redis.php
dictGetRandomKey bug fixed, RANDOMKEY will not block the server anymore
[redis.git] / client-libraries / php / redis.php
CommitLineData
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
17class 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 }
6f864e62 71
72 public function mget($keys) {
73 $this->connect();
74 $this->write("MGET ".implode(" ",$keys)."\r\n");
75 return $this->get_response();
76 }
ed9b544e 77
8d03032a 78 public function incr($name, $amount=1) {
ed9b544e 79 $this->connect();
80 if ($amount == 1)
8d03032a 81 $this->write("INCR $name\r\n");
ed9b544e 82 else
8d03032a 83 $this->write("INCRBY $name $amount\r\n");
bb7dcc1e 84 return $this->get_response();
ed9b544e 85 }
86
8d03032a 87 public function decr($name, $amount=1) {
ed9b544e 88 $this->connect();
89 if ($amount == 1)
8d03032a 90 $this->write("DECR $name\r\n");
ed9b544e 91 else
8d03032a 92 $this->write("DECRBY $name $amount\r\n");
bb7dcc1e 93 return $this->get_response();
ed9b544e 94 }
95
8d03032a 96 public function exists($name) {
ed9b544e 97 $this->connect();
8d03032a 98 $this->write("EXISTS $name\r\n");
bb7dcc1e 99 return $this->get_response();
ed9b544e 100 }
101
8d03032a 102 public function delete($name) {
ed9b544e 103 $this->connect();
8d03032a 104 $this->write("DEL $name\r\n");
bb7dcc1e 105 return $this->get_response();
ed9b544e 106 }
107
8d03032a 108 public function keys($pattern) {
ed9b544e 109 $this->connect();
8d03032a 110 $this->write("KEYS $pattern\r\n");
111 return explode(' ', $this->get_response());
ed9b544e 112 }
113
8d03032a 114 public function randomkey() {
ed9b544e 115 $this->connect();
8d03032a 116 $this->write("RANDOMKEY\r\n");
bb7dcc1e 117 return $this->get_response();
ed9b544e 118 }
119
8d03032a 120 public function rename($src, $dst) {
121 $this->connect();
122 $this->write("RENAME $src $dst\r\n");
123 return $this->get_response();
124 }
125
126 public function renamenx($src, $dst) {
ed9b544e 127 $this->connect();
8d03032a 128 $this->write("RENAMENX $src $dst\r\n");
bb7dcc1e 129 return $this->get_response();
ed9b544e 130 }
131
8d03032a 132 public function expire($name, $time) {
9a2944ac 133 $this->connect();
8d03032a 134 $this->write("EXPIRE $name $time\r\n");
9a2944ac
LM
135 return $this->get_response();
136 }
137
8d03032a 138 public function push($name, $value, $tail=true) {
ed9b544e 139 // default is to append the element to the list
140 $this->connect();
8d03032a 141 $this->write(
ed9b544e 142 ($tail ? 'RPUSH' : 'LPUSH') .
143 " $name " . strlen($value) . "\r\n$value\r\n"
144 );
bb7dcc1e 145 return $this->get_response();
ed9b544e 146 }
8d03032a 147
148 public function lpush($name, $value) {
149 return $this->push($name, $value, false);
150 }
151
152 public function rpush($name, $value) {
153 return $this->push($name, $value, true);
154 }
155
156 public function ltrim($name, $start, $end) {
ed9b544e 157 $this->connect();
8d03032a 158 $this->write("LTRIM $name $start $end\r\n");
bb7dcc1e 159 return $this->get_response();
ed9b544e 160 }
161
8d03032a 162 public function lindex($name, $index) {
ed9b544e 163 $this->connect();
8d03032a 164 $this->write("LINDEX $name $index\r\n");
165 return $this->get_response();
ed9b544e 166 }
167
8d03032a 168 public function pop($name, $tail=true) {
ed9b544e 169 $this->connect();
8d03032a 170 $this->write(
ed9b544e 171 ($tail ? 'RPOP' : 'LPOP') .
172 " $name\r\n"
173 );
8d03032a 174 return $this->get_response();
175 }
176
177 public function lpop($name, $value) {
178 return $this->pop($name, $value, false);
179 }
180
181 public function rpop($name, $value) {
182 return $this->pop($name, $value, true);
ed9b544e 183 }
184
8d03032a 185 public function llen($name) {
ed9b544e 186 $this->connect();
8d03032a 187 $this->write("LLEN $name\r\n");
bb7dcc1e 188 return $this->get_response();
ed9b544e 189 }
190
8d03032a 191 public function lrange($name, $start, $end) {
ed9b544e 192 $this->connect();
8d03032a 193 $this->write("LRANGE $name $start $end\r\n");
bb7dcc1e 194 return $this->get_response();
ed9b544e 195 }
196
8d03032a 197 public function sort($name, $query=false) {
ed9b544e 198 $this->connect();
8d03032a 199 $this->write($query == false ? "SORT $name\r\n" : "SORT $name $query\r\n");
bb7dcc1e 200 return $this->get_response();
ed9b544e 201 }
202
8d03032a 203 public function lset($name, $value, $index) {
ed9b544e 204 $this->connect();
8d03032a 205 $this->write("LSET $name $index " . strlen($value) . "\r\n$value\r\n");
bb7dcc1e 206 return $this->get_response();
ed9b544e 207 }
208
8d03032a 209 public function sadd($name, $value) {
ed9b544e 210 $this->connect();
8d03032a 211 $this->write("SADD $name " . strlen($value) . "\r\n$value\r\n");
bb7dcc1e 212 return $this->get_response();
ed9b544e 213 }
214
8d03032a 215 public function srem($name, $value) {
ed9b544e 216 $this->connect();
8d03032a 217 $this->write("SREM $name " . strlen($value) . "\r\n$value\r\n");
bb7dcc1e 218 return $this->get_response();
ed9b544e 219 }
220
8d03032a 221 public function sismember($name, $value) {
ed9b544e 222 $this->connect();
8d03032a 223 $this->write("SISMEMBER $name " . strlen($value) . "\r\n$value\r\n");
bb7dcc1e 224 return $this->get_response();
ed9b544e 225 }
226
8d03032a 227 public function sinter($sets) {
ed9b544e 228 $this->connect();
8d03032a 229 $this->write('SINTER ' . implode(' ', $sets) . "\r\n");
bb7dcc1e 230 return $this->get_response();
ed9b544e 231 }
232
8d03032a 233 public function smembers($name) {
ed9b544e 234 $this->connect();
8d03032a 235 $this->write("SMEMBERS $name\r\n");
bb7dcc1e 236 return $this->get_response();
ed9b544e 237 }
238
8d03032a 239 public function scard($name) {
ed9b544e 240 $this->connect();
8d03032a 241 $this->write("SCARD $name\r\n");
bb7dcc1e 242 return $this->get_response();
ed9b544e 243 }
244
8d03032a 245 public function select_db($name) {
ed9b544e 246 $this->connect();
8d03032a 247 $this->write("SELECT $name\r\n");
bb7dcc1e 248 return $this->get_response();
ed9b544e 249 }
250
8d03032a 251 public function move($name, $db) {
ed9b544e 252 $this->connect();
8d03032a 253 $this->write("MOVE $name $db\r\n");
bb7dcc1e 254 return $this->get_response();
ed9b544e 255 }
256
8d03032a 257 public function save($background=false) {
ed9b544e 258 $this->connect();
8d03032a 259 $this->write(($background ? "BGSAVE\r\n" : "SAVE\r\n"));
bb7dcc1e 260 return $this->get_response();
ed9b544e 261 }
262
8d03032a 263 public function bgsave($background=false) {
264 return $this->save(true);
265 }
266
267 public function lastsave() {
ed9b544e 268 $this->connect();
8d03032a 269 $this->write("LASTSAVE\r\n");
bb7dcc1e
LM
270 return $this->get_response();
271 }
272
8d03032a 273 public function flushdb($all=false) {
bb7dcc1e 274 $this->connect();
8d03032a 275 $this->write($all ? "FLUSHALL\r\n" : "FLUSHDB\r\n");
bb7dcc1e
LM
276 return $this->get_response();
277 }
8d03032a 278
279 public function flushall() {
280 return $this->flush(true);
281 }
bb7dcc1e 282
8d03032a 283 public function info() {
bb7dcc1e 284 $this->connect();
8d03032a 285 $this->write("INFO\r\n");
bb7dcc1e
LM
286 $info = array();
287 $data =& $this->get_response();
288 foreach (explode("\r\n", $data) as $l) {
289 if (!$l)
290 continue;
291 list($k, $v) = explode(':', $l, 2);
292 $_v = strpos($v, '.') !== false ? (float)$v : (int)$v;
293 $info[$k] = (string)$_v == $v ? $_v : $v;
294 }
295 return $info;
ed9b544e 296 }
297
8d03032a 298 private function write($s) {
ed9b544e 299 while ($s) {
300 $i = fwrite($this->_sock, $s);
bb7dcc1e 301 if ($i == 0) // || $i == strlen($s))
ed9b544e 302 break;
303 $s = substr($s, $i);
304 }
305 }
306
8d03032a 307 private function read($len=1024) {
ed9b544e 308 if ($s = fgets($this->_sock))
309 return $s;
310 $this->disconnect();
311 trigger_error("Cannot read from socket.", E_USER_ERROR);
312 }
313
8d03032a 314 private function get_response() {
315 $data = trim($this->read());
bb7dcc1e
LM
316 $c = $data[0];
317 $data = substr($data, 1);
318 switch ($c) {
319 case '-':
8d03032a 320 trigger_error($data, E_USER_ERROR);
bb7dcc1e
LM
321 break;
322 case '+':
323 return $data;
8d03032a 324 case ':':
325 $i = strpos($data, '.') !== false ? (int)$data : (float)$data;
326 if ((string)$i != $data)
327 trigger_error("Cannot convert data '$c$data' to integer", E_USER_ERROR);
328 return $i;
329 case '$':
330 return $this->get_bulk_reply($c . $data);
bb7dcc1e
LM
331 case '*':
332 $num = (int)$data;
333 if ((string)$num != $data)
334 trigger_error("Cannot convert multi-response header '$data' to integer", E_USER_ERROR);
335 $result = array();
336 for ($i=0; $i<$num; $i++)
8d03032a 337 $result[] =& $this->get_response();
bb7dcc1e
LM
338 return $result;
339 default:
8d03032a 340 trigger_error("Invalid reply type byte: '$c'");
ed9b544e 341 }
bb7dcc1e
LM
342 }
343
8d03032a 344 private function get_bulk_reply($data=null) {
bb7dcc1e 345 if ($data === null)
8d03032a 346 $data = trim($this->read());
bb7dcc1e 347 if ($data == '$-1')
ed9b544e 348 return null;
bb7dcc1e
LM
349 $c = $data[0];
350 $data = substr($data, 1);
8d03032a 351 $bulklen = (int)$data;
352 if ((string)$bulklen != $data)
353 trigger_error("Cannot convert bulk read header '$c$data' to integer", E_USER_ERROR);
bb7dcc1e
LM
354 if ($c != '$')
355 trigger_error("Unkown response prefix for '$c$data'", E_USER_ERROR);
ed9b544e 356 $buffer = '';
8d03032a 357 while ($bulklen) {
358 $data = fread($this->_sock,$bulklen);
359 $bulklen -= strlen($data);
bb7dcc1e 360 $buffer .= $data;
ed9b544e 361 }
8d03032a 362 $crlf = fread($this->_sock,2);
363 return $buffer;
ed9b544e 364 }
8d03032a 365}
ed9b544e 366
975a5b6f 367/*
8d03032a 368$r = new Redis();
975a5b6f 369var_dump($r->set("foo","bar"));
8d03032a 370var_dump($r->get("foo"));
371var_dump($r->info());
975a5b6f 372*/
ed9b544e 373
374?>