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 со значением, равным «Object», а не фактическим объектом PHP. Есть ли способ сохранить объект PHP без его сериализации?

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

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

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

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

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

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

 $xml = $simpleXmlElem->asXML(); 

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

 $simpleXmlElem = simplexml_load_string($xml); 

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

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

Альтернативой является json_encode только параметры, необходимые для восстановления объекта позже. Один из способов сделать это – использовать интерфейс JsonSerialize PHP 5.4. Вы хотите извлечь различные свойства с помощью 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. Вы можете добавить вспомогательный метод для этого или просто вызвать сеттеры.

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

 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:{} 

В дополнение к ответу Аливеба!

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; } } 

'