php-redis — есть ли способ сохранить объект PHP в Redis без его сериализации?

Я пытаюсь сохранить URL-адрес запроса пользователя в качестве ключа и объект PHP, соответствующий этому ключу, в качестве значения в Redis. Я попробовал следующее:

$redisClient = new Redis();
$redisClient->connect('localhost', 6379);
$redisClient->set($_SERVER['REQUEST_URI'], $this->page);
$redisTest = $redisClient->get($_SERVER['REQUEST_URI']);
var_dump($redisTest);

Тем не менее, с этим кодом значение URL-ключа, который хранится в Redis, имеет тип string со значением, равным «Объект» вместо фактического объекта PHP. Есть ли способ сохранить объект PHP без его сериализации?

7

Решение

Как вы можете видеть в Типы данных Redis, Redis поддерживает только эти 5 типов данных:

  • Stirng
  • Список
  • Задавать
  • гашиш
  • Сортированный набор

Итак, нет тип данных объекта и поэтому вы не можете хранить объект непосредственно как значение. Вы должны сначала сериализовать его (или JSON-кодировать его с помощью json_encode функция например).

Есть ли проблема с сериализацией, что вы настаиваете на прямом хранении ваших объектов?

Обновить: Согласно тому, что вы сказали в комментариях, вы можете использовать подход, указанный в этом ответ

Таким образом, вы можете использовать:

$xml = $simpleXmlElem->asXML();

до сериализации, а затем после unserialize(), используйте следующий код:

$simpleXmlElem = simplexml_load_string($xml);

Таким образом, вам не нужно сериализовать встроенный объект PHP, такой как SimpleXmlElement напрямую и проблем не будет.

6

Другие решения

Сериализация будет самым простым способом.

Альтернативой является json_encode только параметры, необходимые для реконструкции объекта позже. Один из способов сделать это — использовать интерфейс PHP 5.4 JsonSerialize. Вы хотите извлечь различные свойства, используя jsonSerialize, а затем предоставить средства для передачи их обратно в ваш класс, когда вы извлекаете элемент из Redis.


class MyPage implements JsonSerializable
{

protected $p1;
protected $p2;

/**
* @param mixed $p1
*/
public function setP1($p1)
{
$this->p1 = $p1;
}

/**
* @param mixed $p2
*/
public function setP2($p2)
{
$this->p2 = $p2;
}

/**
* (PHP 5 &gt;= 5.4.0)<br/>
* Specify data which should be serialized to JSON
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
* @return mixed data which can be serialized by <b>json_encode</b>,
* which is a value of any type other than a resource.
*/
public function jsonSerialize()
{
return [
'p1' => $this->p1,
'p2' => $this->p2,
];
}

}

Таким образом, вы легко сможете восстановить из JSON. Вы можете добавить вспомогательный метод для этого или просто вызвать сеттеры.

3

Вот как я это делаю:

class Cache extends Predis\Client {
protected $prefix = 'myapp:';

public function take($key, $value = null, $ttl = null) {
$value = is_object($value) ? serialize($value) : $value;
$key   = $this->prefix . $key;
if (!$this->exists($key)) {
if (intval($ttl)) {
$this->setEx($key, $ttl, $value);
} else {
$this->set($key, $value);
}
}
return $this->get($key);
}
}

Использование:

$cache = new Cache;

$lorem     = 'Lorem ipsum dolor sit amet';
$loremLong = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';

$cachedLorem          = $cache->take('lorem', $lorem);
$cachedLoremLong      = $cache->take('loremLong', $loremLong);
$cachedLoremTtl       = $cache->take('loremTtl', $lorem, 30);
$cachedLoremGet       = $cache->take('lorem');
$cachedLoremObject    = $cache->take('loremObject', new stdClass);
$cachedLoremObjectTtl = $cache->take('loremObjectTtl', new stdClass, 45);

echo $cachedLorem;
echo $cachedLoremLong;
echo $cachedLoremTtl;
echo $cachedLoremGet;
echo $cachedLoremObject;
echo $cachedLoremObjectTtl;

Выход:

Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
O:8:"stdClass":0:{}
O:8:"stdClass":0:{}
0

Дополнение к ответу Aliweb!

Redis поддерживает целые числа, а также такие действия, как INCR, INCRBY, DECR и DECRBY.

Что касается вопроса:

Сериализация только если не String или Int. Сериализация — это дорогостоящая операция!

на GET и HGET попробуйте посмотреть, что если он сериализован:

private function string_unserialize($str){
$data = @unserialize($str);
if ($str === 'b:0;'){
return 0;
}elseif($data !== false){
return $data;
}else {
return $str;
}
}

0
По вопросам рекламы [email protected]