Created
April 4, 2011 21:54
-
-
Save nrk/902540 to your computer and use it in GitHub Desktop.
Namespace Redis keys transparently using Predis v0.6.x
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// The Predis\NamespacingProfile class was originally conceived for Predis v0.7-dev but it | |
// has been backported to the current stable branch (Predis v0.6.x). Things will be handled | |
// differently with Predis v0.7, see this gist http://gist.github.com/903421 for details. | |
require 'Predis.php'; | |
require 'NamespacingProfile.php'; | |
$profile = new Predis\NamespacingProfile('nrk:', '2.2'); | |
$redis = new Predis\Client('tcp://127.0.0.1', $profile); | |
$redis->mset(array('foo' => 'bar', 'lol' => 'wut')); | |
var_dump($redis->mget('foo', 'lol')); | |
/* | |
array(2) { | |
[0]=> string(3) "bar" | |
[1]=> string(3) "wut" | |
} | |
*/ | |
var_dump($redis->keys('*')); | |
/* | |
array(2) { | |
[0]=> string(7) "nrk:foo" | |
[1]=> string(7) "nrk:lol" | |
} | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Predis; | |
class NamespacingProfile extends RedisServerProfile { | |
private $_prefix; | |
private $_profile; | |
private $_strategies; | |
public function __construct($prefix, $profile = 'default') { | |
$this->_prefix = $prefix; | |
$this->_profile = $this->createProfile($profile); | |
$this->_strategies = $this->getPrefixStrategies(); | |
} | |
protected function getSupportedCommands() { | |
// NOOP | |
} | |
private function createProfile($profile) { | |
if (!$profile instanceof RedisServerProfile) { | |
$profile = RedisServerProfile::get($profile); | |
} | |
$this->checkProfile($profile->getVersion()); | |
return $profile; | |
} | |
protected function checkProfile($profile) { | |
if (!in_array($profile, $this->getSupportedProfiles())) { | |
throw new ClientException("Unsupported profile: $profile"); | |
} | |
} | |
protected function getSupportedProfiles() { | |
return array('1.2', '2.0', '2.2'); | |
} | |
protected function getPrefixStrategies() { | |
$singleKey = function(&$arguments, $prefix) { | |
$arguments[0] = "$prefix{$arguments[0]}"; | |
}; | |
$multiKeys = function(&$arguments, $prefix) { | |
if (count($arguments) === 1 && is_array($arguments[0])) { | |
$arguments = &$arguments[0]; | |
} | |
foreach ($arguments as &$key) { | |
$key = "$prefix$key"; | |
} | |
}; | |
$skipLast = function(&$arguments, $prefix) { | |
$length = count($arguments); | |
for ($i = 0; $i < $length - 1; $i++) { | |
$arguments[$i] = "$prefix{$arguments[$i]}"; | |
} | |
}; | |
$interleavedKeys = function(&$arguments, $prefix) { | |
$length = count($arguments); | |
if ($length === 1 && is_array($arguments[0])) { | |
$oldKvs = &$arguments[0]; | |
$newKvs = array(); | |
foreach ($oldKvs as $key => $value) { | |
$newKvs["$prefix$key"] = $value; | |
unset($oldKvs[$key]); | |
} | |
$arguments[0] = $newKvs; | |
} | |
else { | |
for ($i = 0; $i < $length; $i += 2) { | |
$arguments[$i] = "$prefix{$arguments[$i]}"; | |
} | |
} | |
}; | |
$zunionstore = function(&$arguments, $prefix) { | |
$arguments[0] = "$prefix{$arguments[0]}"; | |
if (is_array($arguments[1])) { | |
foreach ($arguments[1] as &$destinationKey) { | |
$destinationKey = "$prefix$destinationKey"; | |
} | |
$args = &$arguments[1]; | |
$length = count($args); | |
for ($i = 0; $i < $length; $i++) { | |
$arguments[1][$i] = "$prefix{$args[$i]}"; | |
} | |
} | |
else { | |
$length = (int)$arguments[1]; | |
for ($i = 2; $i < $length; $i++) { | |
$arguments[$i] = "$prefix{$arguments[$i]}"; | |
} | |
} | |
}; | |
$sort = function(&$arguments, $prefix) { | |
$arguments[0] = "$prefix{$arguments[0]}"; | |
if (count($arguments) === 1) { | |
return; | |
} | |
foreach ($arguments[1] as $modifier => &$value) { | |
switch (strtoupper($modifier)) { | |
case 'BY': | |
case 'STORE': | |
$value = "$prefix$value"; | |
break; | |
case 'GET': | |
if (is_array($value)) { | |
foreach ($value as &$getItem) { | |
if ($getItem !== '#') { | |
$getItem = "$prefix$getItem"; | |
} | |
} | |
} | |
else { | |
if ($value !== '#') { | |
$value = "$prefix$value"; | |
} | |
} | |
break; | |
} | |
} | |
}; | |
$debug = function(&$arguments, $prefix) { | |
if (count($arguments) === 3 && strtoupper($arguments[1]) == 'OBJECT') { | |
$arguments[2] = "$prefix{$arguments[2]}"; | |
} | |
}; | |
$cmdSingleKey = array( | |
'type', 'exists', 'move', 'expire', 'persist', 'sort', 'expireat', 'ttl', 'append', | |
'getrange', 'setnx', 'decr', 'getset', 'setrange', 'decrby', 'incr', 'set', 'strlen', | |
'get', 'incrby', 'setbit', 'getbit', 'setex', 'hdel', 'hgetall', 'hlen', 'hset', | |
'hexists', 'hincrby', 'hmget', 'hsetnx', 'hget', 'hkeys', 'hmset', 'hvals', 'lindex', | |
'linsert', 'llen', 'lpop', 'lpush', 'lpushx', 'rpushx', 'lrange', 'lrem', 'lset', | |
'ltrim', 'rpop', 'rpush', 'rpushx', 'sadd', 'scard', 'sismember', 'smembers', 'spop', | |
'srandmember', 'srem', 'zadd', 'zcard', 'zcount', 'zincrby', 'zrange', 'zrangebyscore', | |
'zrank', 'zrem', 'zremrangebyrank', 'zremrangebyscore', 'zrevrange', 'zrevrangebyscore', | |
'zrevrank', 'zscore', 'publish', 'keys', | |
); | |
$cmdMultiKeys = array( | |
'del', 'rename', 'renamenx', 'mget', 'rpoplpush', 'sdiff', 'sdiffstore', 'sinter', | |
'sinterstore', 'sunion', 'sunionstore', 'subscribe', 'punsubscribe', 'subscribe', | |
'unsubscribe', 'watch', | |
); | |
return array_merge( | |
array_fill_keys($cmdSingleKey, $singleKey), | |
array_fill_keys($cmdMultiKeys, $multiKeys), | |
array( | |
'blpop' => $skipLast, 'blpop' => $skipLast, 'brpoplpush' => $skipLast, 'smove' => $skipLast, | |
'mset' => $interleavedKeys, 'msetnx' => $interleavedKeys, | |
'zinterstore' => $zunionstore, 'zunionstore' => $zunionstore, | |
'sort' => $sort, 'debug' => $debug | |
) | |
); | |
} | |
public function getProfile() { | |
return $this->_profile; | |
} | |
public function setPrefixStrategy($command, $callable) { | |
$this->_strategies[$command] = $callable; | |
} | |
public function getPrefixStrategy($command) { | |
if (isset($this->_strategies[$command])) { | |
return $this->_strategies[$command]; | |
} | |
} | |
public function createCommand($method, $arguments = array()) { | |
if (isset($this->_strategies[$method])) { | |
$this->_strategies[$method]($arguments, $this->_prefix); | |
} | |
return $this->_profile->createCommand($method, $arguments); | |
} | |
public function getVersion() { | |
return $this->_profile->getVersion(); | |
} | |
public function supportsCommand($command) { | |
return $this->_profile->supportsCommand($command); | |
} | |
public function supportsCommands(Array $commands) { | |
return $this->_profile->supportsCommands($commands); | |
} | |
} |
@mihroot your are definitely right, I didn't notice this error back when I created this gist for an old version of Predis. Luckily the current stable version of Predis ships with a correct prefix strategy for SORT
and there's no need for this gist since it was mostly an hack to get some support for key prefixing back when v0.7 was still considered the development version of Predis. I'll fix this gist anyway, thanks for pointing out!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
On line:112 additional check needed coz SORT command can take 'GET #' param, that don't need to be namespaced.
if($getItem != "#")
$getItem = "$prefix$getItem";