php-redis: ¿hay alguna manera de almacenar objetos PHP en Redis sin serializarlos?

Estoy tratando de almacenar la URL de solicitud del usuario como la clave y un objeto PHP correspondiente a esa clave como el valor en Redis. Intenté lo siguiente:

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

Sin embargo, con este código, el valor de la clave URL que se está almacenando en Redis es un tipo de string con el valor igual a ‘Objeto’ en lugar del objeto PHP real. ¿Hay alguna forma de almacenar un objeto PHP sin serializarlo?

Como puede ver en los tipos de datos de Redis, Redis solo admite estos 5 tipos de datos:

  • Stirng
  • Lista
  • Conjunto
  • Picadillo
  • Conjunto ordenado

Por lo tanto, no hay ningún tipo de datos de objeto y, por lo tanto, no puede almacenar un objeto directamente como un valor. Primero debe serializarlo (o codificarlo mediante JSON con la función json_encode , por ejemplo).

¿Hay algún problema con la serialización que insiste en almacenar sus objetos directamente?

Actualización: de acuerdo con lo que dijo en los comentarios, puede usar el enfoque indicado en esta respuesta

Entonces puedes usar:

 $xml = $simpleXmlElem->asXML(); 

antes de la serialización, y luego de unserialize() , use el siguiente código:

 $simpleXmlElem = simplexml_load_string($xml); 

De esta forma, no tiene que serializar un objeto PHP incorporado como SimpleXmlElement directamente y no habrá problemas.

Serializar sería la forma más directa.

Una alternativa es json_encode solo los parámetros necesarios para reconstruir el objeto más tarde. Una forma de hacerlo es utilizar la interfaz JsonSerialize de PHP 5.4. Querrá extraer varias propiedades usando jsonSerialize y luego proporcionar los medios para devolverlas a su clase cuando extraiga el elemento de 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 >= 5.4.0)
* 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 json_encode, * which is a value of any type other than a resource. */ public function jsonSerialize() { return [ 'p1' => $this->p1, 'p2' => $this->p2, ]; } }

De esta manera, puedes reconstruir fácilmente desde JSON. Puede agregar un método de ayuda para hacer eso o simplemente llamar a los instaladores.

Así es como lo hago:

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

Uso:

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

Salida:

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

¡Una adición a la respuesta de Aliweb!

Redis admite enteros y acciones como INCR, INCRBY, DECR y DECRBY.

En cuanto a la pregunta:

Serializar solo si no es un String o Int. ¡La serialización es una operación costosa!

en GET y HGET intenta ver qué sucede si está serializado:

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