diff --git a/README.markdown b/README.markdown index 09a9b715..e4e0ea1e 100644 --- a/README.markdown +++ b/README.markdown @@ -54,7 +54,7 @@ Furthermore, a pipeline can be initialized on a cluster of redis instances in th same exact way they are created on single connection. Sharding is still transparent to the user: - $redis = Predis\Client::createCluster( + $redis = Predis\Client::create( array('host' => '10.0.0.1', 'port' => 6379), array('host' => '10.0.0.2', 'port' => 6379) ); diff --git a/examples/CommandPipeline.php b/examples/CommandPipeline.php index 7cc84fb0..1edc4d48 100644 --- a/examples/CommandPipeline.php +++ b/examples/CommandPipeline.php @@ -4,8 +4,7 @@ require_once 'SharedConfigurations.php'; // when you have a whole set of consecutive commands to send to // a redis server, you can use a pipeline to improve performances. -$redis = new Predis\Client(REDIS_HOST, REDIS_PORT); -$redis->select(REDIS_DB); +$redis = Predis\Client::create($configurations); $replies = $redis->pipeline(function($pipe) { $pipe->ping(); diff --git a/examples/MultipleSetAndGet.php b/examples/MultipleSetAndGet.php index 6932ec5e..1c5c8f86 100644 --- a/examples/MultipleSetAndGet.php +++ b/examples/MultipleSetAndGet.php @@ -11,8 +11,7 @@ $mkv = array( 'usr:0003' => 'Third user' ); -$redis = new Predis\Client(REDIS_HOST, REDIS_PORT); -$redis->select(REDIS_DB); +$redis = Predis\Client::create($configurations); $redis->mset($mkv); $retval = $redis->mget(array_keys($mkv)); diff --git a/examples/SharedConfigurations.php b/examples/SharedConfigurations.php index b8202aab..8f96e62b 100644 --- a/examples/SharedConfigurations.php +++ b/examples/SharedConfigurations.php @@ -1,7 +1,9 @@ '127.0.0.1', + 'port' => 6379, + 'database' => 15 +); ?> \ No newline at end of file diff --git a/examples/SimpleSetAndGet.php b/examples/SimpleSetAndGet.php index b8a3c648..d6e34327 100644 --- a/examples/SimpleSetAndGet.php +++ b/examples/SimpleSetAndGet.php @@ -3,8 +3,7 @@ require_once 'SharedConfigurations.php'; // simple set and get scenario -$redis = new Predis\Client(REDIS_HOST, REDIS_PORT); -$redis->select(REDIS_DB); +$redis = Predis\Client::create($configurations); $redis->set('library', 'predis'); $retval = $redis->get('library'); diff --git a/lib/Predis.php b/lib/Predis.php index d17743b7..a4c02ec4 100644 --- a/lib/Predis.php +++ b/lib/Predis.php @@ -25,16 +25,85 @@ class Client { $this->_connection->disconnect(); } - public static function createCluster(/* arguments */) { - $cluster = new ConnectionCluster(); - foreach (func_get_args() as $parameters) { - $cluster->add(new Connection($parameters['host'], $parameters['port'])); - } + public static function create(/* arguments */) { + $argv = func_get_args(); + $argc = func_num_args(); + $client = new Client(); - $client->setConnection($cluster); + + if ($argc == 1) { + $client->setConnection($client->createConnection($argv[0])); + } + else if ($argc > 1) { + $cluster = new ConnectionCluster(); + foreach ($argv as $parameters) { + $cluster->add($client->createConnection($parameters)); + } + $client->setConnection($cluster); + } + return $client; } + private static function parseURI($uri) { + $parsed = @parse_url($uri); + + if ($parsed == false || $parsed['scheme'] != 'redis' || $parsed['host'] == null) { + throw new ClientException("Invalid URI: $uri"); + } + + $details = array(); + foreach (explode('&', $parsed['query']) as $kv) { + list($k, $v) = explode('=', $kv); + switch ($k) { + case 'database': + $details['database'] = $v; + break; + case 'password': + $details['password'] = $v; + break; + } + } + + return self::filterConnectionParams(array_merge($parsed, $details)); + } + + private static function filterConnectionParams($parameters) { + return array( + 'host' => $parameters['host'] != null + ? $parameters['host'] + : Connection::DEFAULT_HOST, + 'port' => $parameters['port'] != null + ? (int) $parameters['port'] + : Connection::DEFAULT_PORT, + 'database' => $parameters['database'], + 'password' => $parameters['password'], + ); + } + + private function createConnection($connectionDetails) { + $parameters = is_array($connectionDetails) + ? self::filterConnectionParams($connectionDetails) + : self::parseURI($connectionDetails); + + $connection = new Connection($parameters['host'], $parameters['port']); + + if ($parameters['password'] !== null) { + $connection->pushInitCommand($this->createCommandInstance( + 'auth', + array($parameters['password']) + )); + } + if ($parameters['database'] !== null) { + $connection->pushInitCommand($this->createCommandInstance( + 'select', + array($parameters['database']) + )); + } + + return $connection; + } + private function setConnection(IConnection $connection) { $this->_connection = $connection; } @@ -534,6 +603,7 @@ class Connection implements IConnection { public function __construct($host = self::DEFAULT_HOST, $port = self::DEFAULT_PORT) { $this->_host = $host; $this->_port = $port; + $this->_initCmds = array(); } public function __destruct() { @@ -554,6 +624,10 @@ class Connection implements IConnection { throw new ClientException(trim($errstr), $errno); } stream_set_timeout($this->_socket, self::READ_WRITE_TIMEOUT); + + if (count($this->_initCmds) > 0){ + $this->sendInitializationCommands(); + } } public function disconnect() { @@ -562,6 +636,19 @@ class Connection implements IConnection { } } + public function pushInitCommand(Command $command){ + $this->_initCmds[] = $command; + } + + private function sendInitializationCommands() { + foreach ($this->_initCmds as $command) { + $this->writeCommand($command); + } + foreach ($this->_initCmds as $command) { + $this->readResponse($command); + } + } + public function writeCommand(Command $command) { fwrite($this->getSocket(), $command()); }