// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2017http://thinkphp.cnAll rights reserved.
// +----------------------------------------------------------------------
// | Licensed (http://www.apache.org/licenses/LICENSE-2.0)
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\cache\driver;
use think\cache\Driver;
/**
* Redis緩存驅動,適合單機部署、有前端代理實現高可用的場景,性能最好
* 有需要在業務層實現讀寫分離、或者使用RedisCluster的需求,請使用Redisd驅動
*
* 要求安裝phpredis擴展:https://github.com/nicolasff/phpredis
* @author????robin <1257834076@qq.com>
*/
class Redis extends Driver {
protected $options = [
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 2,
'timeout' => 0,
'expire' => 0,
'persistent' => false,
'prefix' => '',
];
/**
* 構造函數
* @param array $options 緩存參數
* @access public
*/
public function __construct($options = []) {
if (!extension_loaded('redis')) {
throw new \BadFunctionCallException('not support: redis');
}
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
$func = $this->options['persistent'] ? 'pconnect' : 'connect';
$this->handler = new \Redis;
$this->handler->$func($this->options['host'], $this->options['port'], $this->options['timeout']);
if ('' != $this->options['password']) {
$this->handler->auth($this->options['password']);
}
if (0 != $this->options['select']) {
$this->handler->select($this->options['select']);
}
}
/**
* 判斷緩存
* @access public
* @param string $name 緩存變量名
* @return bool
*/
public function has($name) {
return $this->handler->get($this->getCacheKey($name)) ? true : false;
}
/**
* 讀取緩存
* @access public
* @param string $name 緩存變量名
* @param mixed??$default 默認值
* @return mixed
*/
public function get($name, $default = false) {
$value = $this->handler->get($this->getCacheKey($name));
if (is_null($value) || false === $value) {
return $default;
}
$jsonData = json_decode($value, true);
// 檢測是否為JSON數據 true 返回JSON解析數組, false返回源數據 byron sampson<xiaobo.sun@qq.com>
return (null === $jsonData) ? $value : $jsonData;
}
/**
* 寫入緩存
* @access public
* @param string????????????$name 緩存變量名
* @param mixed?????????????$value??存儲數據
* @param integer|\DateTime $expire??有效時間(秒)
* @return boolean
*/
public function set($name, $value, $expire = null) {
if (is_null($expire)) {
$expire = $this->options['expire'];
}
if ($expire instanceof \DateTime) {
$expire = $expire->getTimestamp() - time();
}
if ($this->tag && !$this->has($name)) {
$first = true;
}
$key = $this->getCacheKey($name);
//對數組/對象數據進行緩存處理,保證數據完整性??byron sampson<xiaobo.sun@qq.com>
$value = (is_object($value) || is_array($value)) ? json_encode($value) : $value;
if (is_int($expire) && $expire) {
$result = $this->handler->setex($key, $expire, $value);
} else {
$result = $this->handler->set($key, $value);
}
isset($first) && $this->setTagItem($key);
return $result;
}
/**
* 自增緩存(針對數值緩存)
* @access public
* @param string????$name 緩存變量名
* @param int???????$step 步長
* @return false|int
*/
public function inc($name, $step = 1) {
$key = $this->getCacheKey($name);
return $this->handler->incrby($key, $step);
}
/**
* 自減緩存(針對數值緩存)
* @access public
* @param string????$name 緩存變量名
* @param int???????$step 步長
* @return false|int
*/
public function dec($name, $step = 1) {
$key = $this->getCacheKey($name);
return $this->handler->decrby($key, $step);
}
/**
* 刪除緩存
* @access public
* @param string $name 緩存變量名
* @return boolean
*/
public function rm($name) {
return $this->handler->delete($this->getCacheKey($name));
}
/**
* 清除緩存
* @access public
* @param string $tag 標簽名
* @return boolean
*/
public function clear($tag = null) {
if ($tag) {
// 指定標簽清除
$keys = $this->getTagItem($tag);
foreach ($keys as $key) {
$this->handler->delete($key);
}
$this->rm('tag_' . md5($tag));
return true;
}
return $this->handler->flushDB();
}
//Redis lpush 命令用于將一個或多個值插入到列表的尾部(最右邊)
public function lPush($key, $value) {
return $this->handler->lPush($key, $value);
}
//移除并獲取列表的第一個元素
public function lPop($key) {
return $this->handler->lPop($key);
}
/**
* 獲取值長度
* @param string $key
* @return int
*/
public function lLen($key) {
return $this->handler->lLen($key);
}
//不確定是不是方法不對有待驗證
/**
* 寫入有序列表
* @access public
* @param string $key 列表名
* @param double $score??成員分數
* @param string $member??成員名
* @return boolean
*/
public function Zadd($key, $score, $member) {
if (is_double($score)) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$member = (is_object($member) || is_array($member)) ? json_encode($member) : $member;
$result = $this->handler->Zadd($key, $score, $member);
return $result;
} else {
return false;
}
}
/**
* 統計有序列表成員數
* @access public
* @param string $key 列表名
* @return??int or boolean
*/
public function Zcard($key) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$result = $this->handler->Zcard($key);
return $result;
}
/**
* 獲得有序列表成員排名
* @access public
* @param string??$key 列表名
* @param string $member??成員名
* @return boolean
*/
public function Zrevrank($key, $member) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$member = (is_object($member) || is_array($member)) ? json_encode($member) : $member;
$result = $this->handler->Zrevrank($key, $member);
return $result;
}
/**
* 給有序列表制定成員分數增量
* @access public
* @param string??$key 列表名
* @param float or int $value 增量分數
* @param string $member??成員名
* @return boolean
*/
public function Zincrby($key, $value, $member) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$value = is_numeric($value) ? $value : doubleval($value);
$member = (is_object($member) || is_array($member)) ? json_encode($member) : $member;
$result = $this->handler->Zincrby($key, $value, $member);
return $result;
}
/**
* 獲得有序列表成員分數
* @access public
* @param string??$key 列表名
* @param string $member??成員名
* @return boolean
*/
public function Zscore($key, $member) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$member = (is_object($member) || is_array($member)) ? json_encode($member) : $member;
$result = $this->handler->Zscore($key, $member);
return $result;
}
/**
* 返回有序集中指定區間內的成員,通過索引,分數從高到底
* @access public
* @param string??$key 列表名
* @param int $start
* @param int $end
* @param string $withscore
* @return boolean
*/
public function Zrevrange($key, $start, $end, $withscore = null) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$start = is_int($start) ? $start : intval($start);
$end = is_int($end) ? $end : intval($end);
$result = $this->handler->Zrevrange($key, $start, $end, $withscore);
return $result;
}
/**
* 移除
*/
public function Zremrangebyrank($key, $start, $end) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$start = is_int($start) ? $start : intval($start);
$end = is_int($end) ? $end : intval($end);
$result = $this->handler->Zremrangebyrank($key, $start, $end);
return $result;
}
/*
* 以下都是hash方法
*
* 刪除一個或者多個哈希表字段
* @param???string??$key
* @param???string??$hashKey1
* @param???string??$hashKey2
* @param???string??$hashKeyN
*??@return??int?????Number of deleted fields
* */
public function Hdel($key, $hashKey1) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$hashKey1 = (is_object($hashKey1) || is_array($hashKey1)) ? json_encode($hashKey1) : $hashKey1;
$result = $this->handler->Hdel($key, $hashKey1);
return $result;
}
/* +@return??bool:???If the member exists in the hash table, return TRUE, otherwise return FALSE.
查看哈希表 key 中,指定的字段是否存在。
* @param???string??$key
* @param???string??$hashKey
* */
public function Hexists($key, $hashKey) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$hashKey = (is_object($hashKey) || is_array($hashKey)) ? json_encode($hashKey) : $hashKey;
$result = $this->handler->Hexists($key, $hashKey);
return $result;
}
/* 將哈希表 key 中的字段 field 的值設為 value 。
* @param???string??$key
* @param???string??$hashKey
* @param???string??$value
*??* @return??bool????TRUE if the field was set, FALSE if it was already present.
* */
public function Hset($key, $hashKey, $value) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$hashKey = (is_object($hashKey) || is_array($hashKey)) ? json_encode($hashKey) : $hashKey;
$value = (is_object($value) || is_array($value)) ? json_encode($value) : $value;
$result = $this->handler->Hset($key, $hashKey, $value);
return $result;
}
/* 獲取存儲在哈希表中指定字段的值
* * @param???string??$key
*??@param???string??$hashKey
@return??string??The value, if the command executed successfully BOOL FALSE in case of failure
* */
public function Hget($key, $hashKey) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$hashKey = (is_object($hashKey) || is_array($hashKey)) ? json_encode($hashKey) : $hashKey;
$result = $this->handler->Hget($key, $hashKey);
return $result;
}
/* 獲取存儲在哈希表中所有字段的值
* * @param???string??$key
@return??string??The value, if the command executed successfully BOOL FALSE in case of failure
@Returns the whole hash, as an array of strings indexed by strings.
* */
public function Hgetall($key) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$result = $this->handler->Hgetall($key);
return $result;
}
/* 為哈希表 key 中的指定字段的整數值加上增量 increment 。
* * @param???string??$key
* @param???string??$hashKey
* @param???int?????$value (integer) value that will be added to the member's value
* @return??int?????the new value
* */
public function Hincrby($key, $hashKey, $value) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$hashKey = (is_object($hashKey) || is_array($hashKey)) ? json_encode($hashKey) : $hashKey;
$value = intval($value);
$result = $this->handler->Hincrby($key, $hashKey, $value);
return $result;
}
/* 為哈希表 key 中的指定字段的浮點值加上增量 increment 。
* * @param???string??$key
* @param???string??$hashKey
* @param???float???$increment
* @return??float????the new value
* */
public function Hincrbyfloat($key, $hashKey, $value) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$hashKey = (is_object($hashKey) || is_array($hashKey)) ? json_encode($hashKey) : $hashKey;
$value = floatval($value);
$result = $this->handler->Hincrbyfloat($key, $hashKey, $value);
return $result;
}
/* 獲取存儲在哈希表中所有字段
* @param???string??$key
* @return??array???An array of elements, the keys of the hash. This works like PHP's array_keys().
@Returns the whole hash, as an array of strings indexed by strings.
* */
public function Hkeys($key) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$result = $this->handler->Hkeys($key);
return $result;
}
/* 獲取存儲在哈希表中字段的數量
* @param???string??$key
* @return??int?????the number of items in a hash, FALSE if the key doesn't exist or isn't a hash.
* */
public function Hlen($key) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$result = $this->handler->Hlen($key);
return $result;
}
/* 獲取存儲在哈希表中所有指定字段的值
* * @param???string??$key
* @param???array???$hashKeys
* @return??array???Array An array of elements, the values of the specified fields in the hash,
* */
public function Hmget($key, $hashKeys) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$result = $this->handler->Hmget($key, $hashKeys);
return $result;
}
/* 同時將多個 field-value (域-值)對設置到哈希表 key 中。
* ** @param???string??$key
* @param???array???$hashKeys key → value array
* @return??bool
* */
public function Hmset($key, $hashKeys) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$result = $this->handler->Hmset($key, $hashKeys);
return $result;
}
/* 將哈希表 key 中的字段 field 的值設為 value 。
* @param???string??$key
* @param???string??$hashKey
* @param???string??$value
*??* @return??bool????TRUE if the field was set, FALSE if it was already present.
* */
public function Hsetnx($key, $hashKey, $value) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$hashKey = (is_object($hashKey) || is_array($hashKey)) ? json_encode($hashKey) : $hashKey;
$value = (is_object($value) || is_array($value)) ? json_encode($value) : $value;
$result = $this->handler->Hsetnx($key, $hashKey, $value);
return $result;
}
/* 獲取哈希表中所有值
* @param???string??$key
* @return??array???An array of elements, the values of the hash. This works like PHP's array_values().
* */
public function Hvals($key) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$result = $this->handler->Hvals($key);
return $result;
}
/* 迭代哈希表中的鍵值對。
* @param???string??$key
* @param???string??$pattern
* @param???string??$value
*??* @return??bool????TRUE if the field was set, FALSE if it was already present.
* */
public function Hscan($key, $iterator, $pattern = '', $count = 0) {
$key = (is_object($key) || is_array($key)) ? json_encode($key) : $key;
$pattern = (is_object($pattern) || is_array($pattern)) ? json_encode($pattern) : $pattern;
$iterator = intval($iterator);
$count = intval($count);
$result = $this->handler->Hscan($key, $iterator, $pattern, $count);
return $result;
}
}