]> git.saurik.com Git - redis.git/blob - client-libraries/php/redis.php
FLUSHALL/FLUSHDB no longer sync on disk. Just increment the dirty counter by the...
[redis.git] / client-libraries / php / redis.php
1 <?php
2 /*******************************************************************************
3 * Redis PHP Bindings - http://code.google.com/p/redis/
4 *
5 * Copyright 2009 Ludovico Magnocavallo
6 * Copyright 2009 Salvatore Sanfilippo (ported it to PHP5, fixed some bug)
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 {
18 public $server;
19 public $port;
20 private $_sock;
21
22 public function __construct($host='localhost', $port=6379) {
23 $this->host = $host;
24 $this->port = $port;
25 }
26
27 public function connect() {
28 if ($this->_sock) return;
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)
35 $msg .= "," . ($errno ? " error $errno" : "") .
36 ($errmsg ? " $errmsg" : "");
37 trigger_error("$msg.", E_USER_ERROR);
38 }
39
40 public function disconnect() {
41 if ($this->_sock) @fclose($this->_sock);
42 $this->_sock = null;
43 }
44
45 public function ping() {
46 $this->connect();
47 $this->write("PING\r\n");
48 return $this->get_response();
49 }
50
51 public function do_echo($s) {
52 $this->connect();
53 $this->write("ECHO " . strlen($s) . "\r\n$s\r\n");
54 return $this->get_response();
55 }
56
57 public function set($name, $value, $preserve=false) {
58 $this->connect();
59 $this->write(
60 ($preserve ? 'SETNX' : 'SET') .
61 " $name " . strlen($value) . "\r\n$value\r\n"
62 );
63 return $this->get_response();
64 }
65
66 public function get($name) {
67 $this->connect();
68 $this->write("GET $name\r\n");
69 return $this->get_response();
70 }
71
72 public function incr($name, $amount=1) {
73 $this->connect();
74 if ($amount == 1)
75 $this->write("INCR $name\r\n");
76 else
77 $this->write("INCRBY $name $amount\r\n");
78 return $this->get_response();
79 }
80
81 public function decr($name, $amount=1) {
82 $this->connect();
83 if ($amount == 1)
84 $this->write("DECR $name\r\n");
85 else
86 $this->write("DECRBY $name $amount\r\n");
87 return $this->get_response();
88 }
89
90 public function exists($name) {
91 $this->connect();
92 $this->write("EXISTS $name\r\n");
93 return $this->get_response();
94 }
95
96 public function delete($name) {
97 $this->connect();
98 $this->write("DEL $name\r\n");
99 return $this->get_response();
100 }
101
102 public function keys($pattern) {
103 $this->connect();
104 $this->write("KEYS $pattern\r\n");
105 return explode(' ', $this->get_response());
106 }
107
108 public function randomkey() {
109 $this->connect();
110 $this->write("RANDOMKEY\r\n");
111 return $this->get_response();
112 }
113
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) {
121 $this->connect();
122 $this->write("RENAMENX $src $dst\r\n");
123 return $this->get_response();
124 }
125
126 public function expire($name, $time) {
127 $this->connect();
128 $this->write("EXPIRE $name $time\r\n");
129 return $this->get_response();
130 }
131
132 public function push($name, $value, $tail=true) {
133 // default is to append the element to the list
134 $this->connect();
135 $this->write(
136 ($tail ? 'RPUSH' : 'LPUSH') .
137 " $name " . strlen($value) . "\r\n$value\r\n"
138 );
139 return $this->get_response();
140 }
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) {
151 $this->connect();
152 $this->write("LTRIM $name $start $end\r\n");
153 return $this->get_response();
154 }
155
156 public function lindex($name, $index) {
157 $this->connect();
158 $this->write("LINDEX $name $index\r\n");
159 return $this->get_response();
160 }
161
162 public function pop($name, $tail=true) {
163 $this->connect();
164 $this->write(
165 ($tail ? 'RPOP' : 'LPOP') .
166 " $name\r\n"
167 );
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);
177 }
178
179 public function llen($name) {
180 $this->connect();
181 $this->write("LLEN $name\r\n");
182 return $this->get_response();
183 }
184
185 public function lrange($name, $start, $end) {
186 $this->connect();
187 $this->write("LRANGE $name $start $end\r\n");
188 return $this->get_response();
189 }
190
191 public function sort($name, $query=false) {
192 $this->connect();
193 $this->write($query == false ? "SORT $name\r\n" : "SORT $name $query\r\n");
194 return $this->get_response();
195 }
196
197 public function lset($name, $value, $index) {
198 $this->connect();
199 $this->write("LSET $name $index " . strlen($value) . "\r\n$value\r\n");
200 return $this->get_response();
201 }
202
203 public function sadd($name, $value) {
204 $this->connect();
205 $this->write("SADD $name " . strlen($value) . "\r\n$value\r\n");
206 return $this->get_response();
207 }
208
209 public function srem($name, $value) {
210 $this->connect();
211 $this->write("SREM $name " . strlen($value) . "\r\n$value\r\n");
212 return $this->get_response();
213 }
214
215 public function sismember($name, $value) {
216 $this->connect();
217 $this->write("SISMEMBER $name " . strlen($value) . "\r\n$value\r\n");
218 return $this->get_response();
219 }
220
221 public function sinter($sets) {
222 $this->connect();
223 $this->write('SINTER ' . implode(' ', $sets) . "\r\n");
224 return $this->get_response();
225 }
226
227 public function smembers($name) {
228 $this->connect();
229 $this->write("SMEMBERS $name\r\n");
230 return $this->get_response();
231 }
232
233 public function scard($name) {
234 $this->connect();
235 $this->write("SCARD $name\r\n");
236 return $this->get_response();
237 }
238
239 public function select_db($name) {
240 $this->connect();
241 $this->write("SELECT $name\r\n");
242 return $this->get_response();
243 }
244
245 public function move($name, $db) {
246 $this->connect();
247 $this->write("MOVE $name $db\r\n");
248 return $this->get_response();
249 }
250
251 public function save($background=false) {
252 $this->connect();
253 $this->write(($background ? "BGSAVE\r\n" : "SAVE\r\n"));
254 return $this->get_response();
255 }
256
257 public function bgsave($background=false) {
258 return $this->save(true);
259 }
260
261 public function lastsave() {
262 $this->connect();
263 $this->write("LASTSAVE\r\n");
264 return $this->get_response();
265 }
266
267 public function flushdb($all=false) {
268 $this->connect();
269 $this->write($all ? "FLUSHALL\r\n" : "FLUSHDB\r\n");
270 return $this->get_response();
271 }
272
273 public function flushall() {
274 return $this->flush(true);
275 }
276
277 public function info() {
278 $this->connect();
279 $this->write("INFO\r\n");
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;
290 }
291
292 private function write($s) {
293 while ($s) {
294 $i = fwrite($this->_sock, $s);
295 if ($i == 0) // || $i == strlen($s))
296 break;
297 $s = substr($s, $i);
298 }
299 }
300
301 private function read($len=1024) {
302 if ($s = fgets($this->_sock))
303 return $s;
304 $this->disconnect();
305 trigger_error("Cannot read from socket.", E_USER_ERROR);
306 }
307
308 private function get_response() {
309 $data = trim($this->read());
310 $c = $data[0];
311 $data = substr($data, 1);
312 switch ($c) {
313 case '-':
314 trigger_error($data, E_USER_ERROR);
315 break;
316 case '+':
317 return $data;
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);
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++)
331 $result[] =& $this->get_response();
332 return $result;
333 default:
334 trigger_error("Invalid reply type byte: '$c'");
335 }
336 }
337
338 private function get_bulk_reply($data=null) {
339 if ($data === null)
340 $data = trim($this->read());
341 if ($data == '$-1')
342 return null;
343 $c = $data[0];
344 $data = substr($data, 1);
345 $bulklen = (int)$data;
346 if ((string)$bulklen != $data)
347 trigger_error("Cannot convert bulk read header '$c$data' to integer", E_USER_ERROR);
348 if ($c != '$')
349 trigger_error("Unkown response prefix for '$c$data'", E_USER_ERROR);
350 $buffer = '';
351 while ($bulklen) {
352 $data = fread($this->_sock,$bulklen);
353 $bulklen -= strlen($data);
354 $buffer .= $data;
355 }
356 $crlf = fread($this->_sock,2);
357 return $buffer;
358 }
359 }
360
361 /*
362 $r = new Redis();
363 var_dump($r->set("foo","bar"));
364 var_dump($r->get("foo"));
365 var_dump($r->info());
366 */
367
368 ?>