11

我正在尝试将用户的请求 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其值等于“对象”,而不是实际的 PHP 对象。有没有办法在不序列化的情况下存储 PHP 对象?

4

4 回答 4

11

Redis 数据类型中可以看到,Redis 只支持这 5 种数据类型:

  • 细绳
  • 列表
  • 哈希
  • 排序集

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

您坚持直接存储对象的序列化是否有任何问题?

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

所以你可以使用:

$xml = $simpleXmlElem->asXML();

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

$simpleXmlElem = simplexml_load_string($xml);

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

于 2014-11-03T16:17:24.400 回答
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 &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 进行重构。您可以添加一个辅助方法来做到这一点,或者只是调用设置器。

于 2014-11-03T16:16:00.423 回答
1

这是我的做法:

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:{}
于 2016-11-15T11:04:02.447 回答
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;
        }
    }

'

于 2017-05-05T09:12:43.490 回答