我正在尝试将用户的请求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);
但是,使用此代码,存储在Redis中的URL键的值是string
的类型,其值等于'Object'而不是实际的PHP对象。有没有办法存储PHP对象而不进行序列化?
答案 0 :(得分:6)
正如您在Redis data types中所看到的,Redis仅支持这5种数据类型:
因此,没有对象数据类型,因此您无法将对象直接存储为值。您必须先将其序列化(或者使用json_encode
函数对其进行JSON编码)。
序列化是否存在直接存储对象的问题?
更新:根据您在评论中所说的内容,您可以使用此answer
中指明的方法所以你可以使用:
$xml = $simpleXmlElem->asXML();
在序列化之前,然后在unserialize()
之后,使用以下代码:
$simpleXmlElem = simplexml_load_string($xml);
通过这种方式,您不必直接序列化SimpleXmlElement
之类的PHP内置对象,也不会出现问题。
答案 1 :(得分:3)
序列化将是最直接的方式。
另一种方法是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 >= 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重建。您可以添加辅助方法来执行此操作或只调用setter。
答案 2 :(得分:0)
我是这样做的:
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:{}
答案 3 :(得分: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;
}
}