繁体   English   中英

php-redis - 有没有办法在Redis中存储PHP对象而不进行序列化?

[英]php-redis - Is there a way to store PHP object in Redis without serializing it?

我试图将用户的请求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对象而不进行序列化?

正如您在Redis数据类型中看到的,Redis仅支持以下5种数据类型:

  • Stirng
  • 名单
  • 哈希
  • 排序集

因此,没有对象数据类型 ,因此您无法将对象直接存储为值。 您必须先将其序列化(或者使用json_encode函数对其进行JSON编码)。

串行化是否存在直接存储对象的问题?

更新:根据您在评论中所说的内容,您可以使用此答案中指出的方法

所以你可以使用:

$xml = $simpleXmlElem->asXML();

在序列化之前,然后在unserialize() ,使用以下代码:

$simpleXmlElem = simplexml_load_string($xml);

这样,您不必直接序列化像SimpleXmlElement这样的PHP内置对象,也不会有任何问题。

序列化将是最直接的方式。

另一种方法是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重建。 您可以添加辅助方法来执行此操作或只调用setter。

我是这样做的:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM