Predis。如何设置西里尔文键?

时间:2016-04-27 10:27:36

标签: php redis predis

我尝试执行下一个命令。

Redis::hincrby('sentiment_combined:positive', 'рыжий кот', 1);

此命令适用于拉丁语键,例如'orange cat'。但是'рыжий кот'我有下一个错误:

[Predis\Response\ServerException]         
ERR Protocol error: expected '$', got '�'  <

我已将日志添加到Predis Predis\Connection\StreamConnection::write()

print_r($buffer);echo "---$written---\n";

我在控制台中观察输出:

*2
$6
SELECT
$1
0
---23---
*4
$7
HINCRBY
$27
sentiment_combined:positive
$9
рыжий кот
$1
1
---81---

Redis支持any keys。如何在Predis中克服这个限制?

2 个答案:

答案 0 :(得分:1)

问题解决了:https://github.com/nrk/predis/issues/328

php.ini中mbstring.func_overload = 6的原因。必须是mbstring.func_overload = 0

答案 1 :(得分:0)

use Predis\Response\Status as StatusResponse;

class MbStreamConnection extends \Predis\Connection\StreamConnection
{
    protected function write($buffer)
    {
        $socket = $this->getResource();

        $buffer = iconv('utf-8', 'windows-1251', $buffer);
        while (($length = mb_strlen($buffer, '8bit')) > 0)
        {
            $written = @fwrite($socket, $buffer, $length);

            if ($length === $written) {
                return;
            }

            if ($written === false) {
                $this->onConnectionError('Error while writing bytes to the server');
            }

            $buffer = substr($buffer, $written);
        }

        return;
    }

    /**
     * {@inheritdoc}
     */
    public function read()
    {
        $socket = $this->getResource();
        $chunk = fgets($socket);

        $chunk = iconv('windows-1251', 'utf-8', $chunk);

        if ($chunk === false || $chunk === '') {
            $this->onConnectionError('Error while reading line from the server.');
        }

        $prefix = $chunk[0];
        $payload = substr($chunk, 1, -2);

        switch ($prefix) {
            case '+':
                return StatusResponse::get($payload);

            case '$':
                $size = (int) $payload;

                if ($size === -1) {
                    return;
                }

                $bulkData = '';
                $bytesLeft = ($size += 2);

                do {
                    $chunk = fread($socket, min($bytesLeft, 4096));

                    if ($chunk === false || $chunk === '') {
                        $this->onConnectionError('Error while reading bytes from the server.');
                    }

                    $bulkData .= $chunk;
                    $bytesLeft = $size - mb_strlen($bulkData, '8bit');

                } while ($bytesLeft > 0);

                $tmp = mb_substr($bulkData, 0, -2);
                $tmp = iconv('windows-1251', 'utf-8', $tmp);
                return $tmp;

            case '*':
                $count = (int) $payload;

                if ($count === -1) {
                    return;
                }

                $multibulk = array();

                for ($i = 0; $i < $count; ++$i) {
                    $multibulk[$i] = $this->read();
                }

                return $multibulk;

            case ':':
                $integer = (int) $payload;
                return $integer == $payload ? $integer : $payload;

            case '-':
                return new ErrorResponse($payload);

            default:
                $this->onProtocolError("Unknown response prefix: '$prefix'.");

                return;
        }
    }
}

in connections params使用MbStreamConnection

$client = new \Predis\Client('tcp://localhost:6379', [
                'scheme' => 'tcp',
                'host'   => 'localhost',
                'port'   => 6379,
                'connections' => [
                    'tcp' => 'MbStreamConnection'
                ],
                'parameters' => [
                    'password' => '',
                     ]
                ]);