FuelPHPでRedisを使う場合、基本的にCoreのRedis_Dbを使う事になると思いますが、
MGETなどの可変長のデータを取り扱いたいときに配列がサポートされていないので今一使い辛いです。
他のredisライブラリを使うなどの方法があると思いますけど今回Coreを拡張してみます。
拡張のやり方自体は日本語サイト参照
拡張対象の関数
fuel/core/classes/redis/db.php
/**
* @param $name
* @param $args
* @return $this|array
* @throws \RedisException
*/
public function __call($name, $args)
{
// build the Redis unified protocol command
array_unshift($args, strtoupper($name));
$command = '*' . count($args) . CRLF;
foreach ($args as $arg) {
$command .= '$' . strlen($arg) . CRLF . $arg . CRLF;
}
// add it to the pipeline queue
$this->queue[] = $command;
if ($this->pipelined)
{
return $this;
}
else
{
return $this->execute();
}
}
主にredisサーバに送るデータを作ってる前半箇所を弄ります。
array_unshift($args, strtoupper($name));
$command = '*' . count($args) . CRLF;
foreach ($args as $arg) {
$command .= '$' . strlen($arg) . CRLF . $arg . CRLF;
}
##実装
拡張内容としては配列だった場合に配列を含めた要素をカウントしつつ配列そのものをデータとして使います。
fuel/app/classes/redis/db.php
public function __call($name, $args)
{
// build the Redis unified protocol command
$values = $args[0];
$name = strtoupper($name);
array_unshift($args, $name);
$cnt = is_array($values) ? count($values) + 1 : count($args);
$command = '*' . $cnt . CRLF;
if (is_array($values)) {
$command .= '$' . strlen($name) . CRLF . $name . CRLF;
$args = $values;
}
foreach ($args as $arg) {
$command .= '$' . strlen($arg) . CRLF . $arg . CRLF;
}
…
}
__callではなくそれぞれのredisコマンドに合わせて関数を作れば、
$key=>$valueに対応することでMSETとかもつかいやすくなるかと思います。
fuel/app/classes/redis/db.php
public function mset($args)
{
$cnt = count($args) * 2 + 1;
$command = '*' . $cnt . CRLF;
$command .= '$' . 4 . CRLF . 'MSET' . CRLF;
foreach ($args as $key => $value) {
$command .= '$' . strlen($key) . CRLF . $key . CRLF;
$command .= '$' . strlen($value) . CRLF . $value . CRLF;
}
// add it to the pipeline queue
$this->queue[] = $command;
if ($this->pipelined)
{
return $this;
}
else
{
return $this->execute();
}
}
##簡単な解説
FuelPHPのRedisはライブラリなどは使わずにソケット通信で実現しているので、
プロトコルに合わせた文字列を作る必要があります。
プロトコルっていうと何か凄く難しい印象があるけど、
Redisのプロトコルを調べてみたら日本語マニュアルの説明にある通り思ったより簡単でした。
Coreの実装を見るとプロトコルに合わせた文字列を作って送っているのがわかります。