PHP client ported to PHP5 and fixed

This commit is contained in:
antirez 2009-04-21 19:43:02 +02:00
parent 3c910136c1
commit 8d03032a83
2 changed files with 176 additions and 142 deletions

View File

@ -3,6 +3,7 @@
* Redis PHP Bindings - http://code.google.com/p/redis/ * Redis PHP Bindings - http://code.google.com/p/redis/
* *
* Copyright 2009 Ludovico Magnocavallo * Copyright 2009 Ludovico Magnocavallo
* Copyright 2009 Salvatore Sanfilippo (ported it to PHP5, fixed some bug)
* Released under the same license as Redis. * Released under the same license as Redis.
* *
* Version: 0.1 * Version: 0.1
@ -14,240 +15,268 @@
class Redis { class Redis {
public $server;
public $port;
private $_sock;
var $server; public function __construct($host='localhost', $port=6379) {
var $port;
var $_sock;
function Redis($host='localhost', $port=6379) {
$this->host = $host; $this->host = $host;
$this->port = $port; $this->port = $port;
} }
function connect() { public function connect() {
if ($this->_sock) if ($this->_sock) return;
return;
if ($sock = fsockopen($this->host, $this->port, $errno, $errstr)) { if ($sock = fsockopen($this->host, $this->port, $errno, $errstr)) {
$this->_sock = $sock; $this->_sock = $sock;
return; return;
} }
$msg = "Cannot open socket to {$this->host}:{$this->port}"; $msg = "Cannot open socket to {$this->host}:{$this->port}";
if ($errno || $errmsg) if ($errno || $errmsg)
$msg .= "," . ($errno ? " error $errno" : "") . ($errmsg ? " $errmsg" : ""); $msg .= "," . ($errno ? " error $errno" : "") .
($errmsg ? " $errmsg" : "");
trigger_error("$msg.", E_USER_ERROR); trigger_error("$msg.", E_USER_ERROR);
} }
function disconnect() { public function disconnect() {
if ($this->_sock) if ($this->_sock) @fclose($this->_sock);
@fclose($this->_sock);
$this->_sock = null; $this->_sock = null;
} }
function &ping() { public function ping() {
$this->connect(); $this->connect();
$this->_write("PING\r\n"); $this->write("PING\r\n");
return $this->get_response(); return $this->get_response();
} }
function &do_echo($s) { public function do_echo($s) {
$this->connect(); $this->connect();
$this->_write("ECHO " . strlen($s) . "\r\n$s\r\n"); $this->write("ECHO " . strlen($s) . "\r\n$s\r\n");
return $this->_get_value(); return $this->get_response();
} }
function &set($name, $value, $preserve=false) { public function set($name, $value, $preserve=false) {
$this->connect(); $this->connect();
$this->_write( $this->write(
($preserve ? 'SETNX' : 'SET') . ($preserve ? 'SETNX' : 'SET') .
" $name " . strlen($value) . "\r\n$value\r\n" " $name " . strlen($value) . "\r\n$value\r\n"
); );
return $this->get_response(); return $this->get_response();
} }
function &get($name) { public function get($name) {
$this->connect(); $this->connect();
$this->_write("GET $name\r\n"); $this->write("GET $name\r\n");
return $this->_get_value(); return $this->get_response();
} }
function &incr($name, $amount=1) { public function incr($name, $amount=1) {
$this->connect(); $this->connect();
if ($amount == 1) if ($amount == 1)
$this->_write("INCR $name\r\n"); $this->write("INCR $name\r\n");
else else
$this->_write("INCRBY $name $amount\r\n"); $this->write("INCRBY $name $amount\r\n");
return $this->get_response(); return $this->get_response();
} }
function &decr($name, $amount=1) { public function decr($name, $amount=1) {
$this->connect(); $this->connect();
if ($amount == 1) if ($amount == 1)
$this->_write("DECR $name\r\n"); $this->write("DECR $name\r\n");
else else
$this->_write("DECRBY $name $amount\r\n"); $this->write("DECRBY $name $amount\r\n");
return $this->get_response(); return $this->get_response();
} }
function &exists($name) { public function exists($name) {
$this->connect(); $this->connect();
$this->_write("EXISTS $name\r\n"); $this->write("EXISTS $name\r\n");
return $this->get_response(); return $this->get_response();
} }
function &delete($name) { public function delete($name) {
$this->connect(); $this->connect();
$this->_write("DEL $name\r\n"); $this->write("DEL $name\r\n");
return $this->get_response(); return $this->get_response();
} }
function &keys($pattern) { public function keys($pattern) {
$this->connect(); $this->connect();
$this->_write("KEYS $pattern\r\n"); $this->write("KEYS $pattern\r\n");
return explode(' ', $this->_get_value()); return explode(' ', $this->get_response());
} }
function &randomkey() { public function randomkey() {
$this->connect(); $this->connect();
$this->_write("RANDOMKEY\r\n"); $this->write("RANDOMKEY\r\n");
return $this->get_response(); return $this->get_response();
} }
function &rename($src, $dst, $preserve=False) { public function rename($src, $dst) {
$this->connect(); $this->connect();
$this->_write($preserve ? "RENAMENX $src $dst\r\n" : "RENAME $src $dst\r\n"); $this->write("RENAME $src $dst\r\n");
return $this->get_response(); return $this->get_response();
} }
function &expire($name, $time) { public function renamenx($src, $dst) {
$this->connect(); $this->connect();
$this->_write("EXPIRE $name $time\r\n"); $this->write("RENAMENX $src $dst\r\n");
return $this->get_response(); return $this->get_response();
} }
function &push($name, $value, $tail=true) { public function expire($name, $time) {
$this->connect();
$this->write("EXPIRE $name $time\r\n");
return $this->get_response();
}
public function push($name, $value, $tail=true) {
// default is to append the element to the list // default is to append the element to the list
$this->connect(); $this->connect();
$this->_write( $this->write(
($tail ? 'RPUSH' : 'LPUSH') . ($tail ? 'RPUSH' : 'LPUSH') .
" $name " . strlen($value) . "\r\n$value\r\n" " $name " . strlen($value) . "\r\n$value\r\n"
); );
return $this->get_response(); return $this->get_response();
} }
function &ltrim($name, $start, $end) { public function lpush($name, $value) {
return $this->push($name, $value, false);
}
public function rpush($name, $value) {
return $this->push($name, $value, true);
}
public function ltrim($name, $start, $end) {
$this->connect(); $this->connect();
$this->_write("LTRIM $name $start $end\r\n"); $this->write("LTRIM $name $start $end\r\n");
return $this->get_response(); return $this->get_response();
} }
function &lindex($name, $index) { public function lindex($name, $index) {
$this->connect(); $this->connect();
$this->_write("LINDEX $name $index\r\n"); $this->write("LINDEX $name $index\r\n");
return $this->_get_value(); return $this->get_response();
} }
function &pop($name, $tail=true) { public function pop($name, $tail=true) {
$this->connect(); $this->connect();
$this->_write( $this->write(
($tail ? 'RPOP' : 'LPOP') . ($tail ? 'RPOP' : 'LPOP') .
" $name\r\n" " $name\r\n"
); );
return $this->_get_value();
}
function &llen($name) {
$this->connect();
$this->_write("LLEN $name\r\n");
return $this->get_response(); return $this->get_response();
} }
function &lrange($name, $start, $end) { public function lpop($name, $value) {
return $this->pop($name, $value, false);
}
public function rpop($name, $value) {
return $this->pop($name, $value, true);
}
public function llen($name) {
$this->connect(); $this->connect();
$this->_write("LRANGE $name $start $end\r\n"); $this->write("LLEN $name\r\n");
return $this->get_response(); return $this->get_response();
} }
function &sort($name, $query=false) { public function lrange($name, $start, $end) {
$this->connect(); $this->connect();
$this->_write($query == false ? "SORT $name\r\n" : "SORT $name $query\r\n"); $this->write("LRANGE $name $start $end\r\n");
return $this->get_response(); return $this->get_response();
} }
function &lset($name, $value, $index) { public function sort($name, $query=false) {
$this->connect(); $this->connect();
$this->_write("LSET $name $index " . strlen($value) . "\r\n$value\r\n"); $this->write($query == false ? "SORT $name\r\n" : "SORT $name $query\r\n");
return $this->get_response(); return $this->get_response();
} }
function &sadd($name, $value) { public function lset($name, $value, $index) {
$this->connect(); $this->connect();
$this->_write("SADD $name " . strlen($value) . "\r\n$value\r\n"); $this->write("LSET $name $index " . strlen($value) . "\r\n$value\r\n");
return $this->get_response(); return $this->get_response();
} }
function &srem($name, $value) { public function sadd($name, $value) {
$this->connect(); $this->connect();
$this->_write("SREM $name " . strlen($value) . "\r\n$value\r\n"); $this->write("SADD $name " . strlen($value) . "\r\n$value\r\n");
return $this->get_response(); return $this->get_response();
} }
function &sismember($name, $value) { public function srem($name, $value) {
$this->connect(); $this->connect();
$this->_write("SISMEMBER $name " . strlen($value) . "\r\n$value\r\n"); $this->write("SREM $name " . strlen($value) . "\r\n$value\r\n");
return $this->get_response(); return $this->get_response();
} }
function &sinter($sets) { public function sismember($name, $value) {
$this->connect(); $this->connect();
$this->_write('SINTER ' . implode(' ', $sets) . "\r\n"); $this->write("SISMEMBER $name " . strlen($value) . "\r\n$value\r\n");
return $this->get_response(); return $this->get_response();
} }
function &smembers($name) { public function sinter($sets) {
$this->connect(); $this->connect();
$this->_write("SMEMBERS $name\r\n"); $this->write('SINTER ' . implode(' ', $sets) . "\r\n");
return $this->get_response(); return $this->get_response();
} }
function &scard($name) { public function smembers($name) {
$this->connect(); $this->connect();
$this->_write("SCARD $name\r\n"); $this->write("SMEMBERS $name\r\n");
return $this->get_response(); return $this->get_response();
} }
function &select_db($name) { public function scard($name) {
$this->connect(); $this->connect();
$this->_write("SELECT $name\r\n"); $this->write("SCARD $name\r\n");
return $this->get_response(); return $this->get_response();
} }
function &move($name, $db) { public function select_db($name) {
$this->connect(); $this->connect();
$this->_write("MOVE $name $db\r\n"); $this->write("SELECT $name\r\n");
return $this->get_response(); return $this->get_response();
} }
function &save($background=false) { public function move($name, $db) {
$this->connect(); $this->connect();
$this->_write(($background ? "BGSAVE\r\n" : "SAVE\r\n")); $this->write("MOVE $name $db\r\n");
return $this->get_response(); return $this->get_response();
} }
function &lastsave() { public function save($background=false) {
$this->connect(); $this->connect();
$this->_write("LASTSAVE\r\n"); $this->write(($background ? "BGSAVE\r\n" : "SAVE\r\n"));
return $this->get_response(); return $this->get_response();
} }
function &flush($all=false) { public function bgsave($background=false) {
return $this->save(true);
}
public function lastsave() {
$this->connect(); $this->connect();
$this->_write($all ? "FLUSH\r\n" : "FLUSHDB\r\n"); $this->write("LASTSAVE\r\n");
return $this->get_response(); return $this->get_response();
} }
function &info() { public function flushdb($all=false) {
$this->connect(); $this->connect();
$this->_write("INFO\r\n"); $this->write($all ? "FLUSHALL\r\n" : "FLUSHDB\r\n");
return $this->get_response();
}
public function flushall() {
return $this->flush(true);
}
public function info() {
$this->connect();
$this->write("INFO\r\n");
$info = array(); $info = array();
$data =& $this->get_response(); $data =& $this->get_response();
foreach (explode("\r\n", $data) as $l) { foreach (explode("\r\n", $data) as $l) {
@ -260,7 +289,7 @@ class Redis {
return $info; return $info;
} }
function &_write($s) { private function write($s) {
while ($s) { while ($s) {
$i = fwrite($this->_sock, $s); $i = fwrite($this->_sock, $s);
if ($i == 0) // || $i == strlen($s)) if ($i == 0) // || $i == strlen($s))
@ -269,64 +298,68 @@ class Redis {
} }
} }
function &_read($len=1024) { private function read($len=1024) {
if ($s = fgets($this->_sock)) if ($s = fgets($this->_sock))
return $s; return $s;
$this->disconnect(); $this->disconnect();
trigger_error("Cannot read from socket.", E_USER_ERROR); trigger_error("Cannot read from socket.", E_USER_ERROR);
} }
function &get_response() { private function get_response() {
$data = trim($this->_read()); $data = trim($this->read());
$c = $data[0]; $c = $data[0];
$data = substr($data, 1); $data = substr($data, 1);
switch ($c) { switch ($c) {
case '-': case '-':
trigger_error(substr($data, 0, 4) == 'ERR ' ? substr($data, 4) : $data, E_USER_ERROR); trigger_error($data, E_USER_ERROR);
break; break;
case '+': case '+':
return $data; return $data;
case ':':
$i = strpos($data, '.') !== false ? (int)$data : (float)$data;
if ((string)$i != $data)
trigger_error("Cannot convert data '$c$data' to integer", E_USER_ERROR);
return $i;
case '$':
return $this->get_bulk_reply($c . $data);
case '*': case '*':
$num = (int)$data; $num = (int)$data;
if ((string)$num != $data) if ((string)$num != $data)
trigger_error("Cannot convert multi-response header '$data' to integer", E_USER_ERROR); trigger_error("Cannot convert multi-response header '$data' to integer", E_USER_ERROR);
$result = array(); $result = array();
for ($i=0; $i<$num; $i++) for ($i=0; $i<$num; $i++)
$result[] =& $this->_get_value(); $result[] =& $this->get_response();
return $result; return $result;
default: default:
return $this->_get_value($c . $data); trigger_error("Invalid reply type byte: '$c'");
} }
} }
function &_get_value($data=null) { private function get_bulk_reply($data=null) {
if ($data === null) if ($data === null)
$data =& trim($this->_read()); $data = trim($this->read());
if ($data == '$-1') if ($data == '$-1')
return null; return null;
$c = $data[0]; $c = $data[0];
$data = substr($data, 1); $data = substr($data, 1);
$i = strpos($data, '.') !== false ? (int)$data : (float)$data; $bulklen = (int)$data;
if ((string)$i != $data) if ((string)$bulklen != $data)
trigger_error("Cannot convert data '$c$data' to integer", E_USER_ERROR); trigger_error("Cannot convert bulk read header '$c$data' to integer", E_USER_ERROR);
if ($c == ':')
return $i;
if ($c != '$') if ($c != '$')
trigger_error("Unkown response prefix for '$c$data'", E_USER_ERROR); trigger_error("Unkown response prefix for '$c$data'", E_USER_ERROR);
$buffer = ''; $buffer = '';
while (true) { while ($bulklen) {
$data =& $this->_read(); $data = fread($this->_sock,$bulklen);
$i -= strlen($data); $bulklen -= strlen($data);
$buffer .= $data; $buffer .= $data;
if ($i < 0)
break;
} }
return substr($buffer, 0, -2); $crlf = fread($this->_sock,2);
return $buffer;
} }
} }
//$r =& new Redis(); $r = new Redis();
//var_dump($r->info()); var_dump($r->get("foo"));
var_dump($r->info());
?> ?>

View File

@ -7,7 +7,8 @@ require_once('redis.php');
$r =& new Redis('localhost'); $r =& new Redis('localhost');
$r->connect(); $r->connect();
$r->select_db(9); $r->select_db(9);
$r->flush(); $r->flushdb();
echo "<pre>\n";
echo $r->ping() . "\n"; echo $r->ping() . "\n";
echo $r->do_echo('ECHO test') . "\n"; echo $r->do_echo('ECHO test') . "\n";
echo "SET aaa " . $r->set('aaa', 'bbb') . "\n"; echo "SET aaa " . $r->set('aaa', 'bbb') . "\n";
@ -29,15 +30,15 @@ echo 'SET a1 a2 a3' . $r->set('a1', 'a') . $r->set('a2', 'b') . $r->set('a3', 'c
echo 'KEYS a* ' . print_r($r->keys('a*'), true) . "\n"; echo 'KEYS a* ' . print_r($r->keys('a*'), true) . "\n";
echo 'RANDOMKEY ' . $r->randomkey('a*') . "\n"; echo 'RANDOMKEY ' . $r->randomkey('a*') . "\n";
echo 'RENAME a1 a0 ' . $r->rename('a1', 'a0') . "\n"; echo 'RENAME a1 a0 ' . $r->rename('a1', 'a0') . "\n";
echo 'RENAMENX a0 a2 ' . $r->rename('a0', 'a2', true) . "\n"; echo 'RENAMENX a0 a2 ' . $r->renamenx('a0', 'a2') . "\n";
echo 'RENAMENX a0 a1 ' . $r->rename('a0', 'a1', true) . "\n"; echo 'RENAMENX a0 a1 ' . $r->renamenx('a0', 'a1') . "\n";
echo 'LPUSH a0 aaa ' . $r->push('a0', 'aaa') . "\n"; echo 'LPUSH a0 aaa ' . $r->push('a0', 'aaa') . "\n";
echo 'LPUSH a0 bbb ' . $r->push('a0', 'bbb') . "\n"; echo 'LPUSH a0 bbb ' . $r->push('a0', 'bbb') . "\n";
echo 'RPUSH a0 ccc ' . $r->push('a0', 'ccc', false) . "\n"; echo 'RPUSH a0 ccc ' . $r->push('a0', 'ccc', false) . "\n";
echo 'LLEN a0 ' . $r->llen('a0') . "\n"; echo 'LLEN a0 ' . $r->llen('a0') . "\n";
echo 'LRANGE sdkjhfskdjfh 0 100 ' . print_r($r->lrange('sdkjhfskdjfh', 0, 100), true) . "\n"; echo 'LRANGE sdkjhfskdjfh 0 100 ' . print_r($r->lrange('sdkjhfskdjfh', 0, 100), true) . "\n";
echo 'LRANGE a0 0 0 ' . print_r($r->lrange('sdkjhfskdjfh', 0, 0), true) . "\n"; echo 'LRANGE a0 0 0 ' . print_r($r->lrange('a0', 0, 0), true) . "\n";
echo 'LRANGE a0 0 100 ' . print_r($r->lrange('a0', 0, 100), true) . "\n"; echo 'LRANGE a0 0 100 ' . print_r($r->lrange('a0', 0, 100), true) . "\n";
echo 'LTRIM a0 0 1 ' . $r->ltrim('a0', 0, 1) . "\n"; echo 'LTRIM a0 0 1 ' . $r->ltrim('a0', 0, 1) . "\n";
echo 'LRANGE a0 0 100 ' . print_r($r->lrange('a0', 0, 100), true) . "\n"; echo 'LRANGE a0 0 100 ' . print_r($r->lrange('a0', 0, 100), true) . "\n";
@ -82,5 +83,5 @@ echo 'BGSAVE ' . $r->save(true) . "\n";
echo 'LASTSAVE ' . $r->lastsave() . "\n"; echo 'LASTSAVE ' . $r->lastsave() . "\n";
echo 'INFO ' . print_r($r->info()) . "\n"; echo 'INFO ' . print_r($r->info()) . "\n";
echo "</pre>\n";
?> ?>