<?php declare(strict_types=1); ini_set('display_errors', 'On'); error_reporting(-1); $redis = new Redis(); $redis->connect('localhost'); $redis->auth('************'); /** * 设置缓存 * * @param string $key 缓存KEY * @param mixed $value 缓存VALUE(支持各种数据类型,不需要预先转成字符串) * @param int $timeout 有效时间(单位:秒),若设为0则永久有效 * @return bool true=设置缓存成功|false=设置缓存失败 */ function set_cache(string $key, mixed $value, int $timeout): bool { global $redis; // 重要说明:不管缓存VALUE是什么数据类型,都将其作为数组元素构造一个数组 $array = [$value]; $json = json_encode($array); return $redis->set($key, $json, $timeout); } /** * 获取缓存 * * @param string $key 缓存KEY * @return mixed 缓存VALUE(设置缓存时是什么类型,获取到的就是什么类型) */ function get_cache(string $key): mixed { global $redis; // 在设置缓存时对数据进行了json_encode()处理,所以这里要json_decode() $json = $redis->get($key); $array = json_decode($json, true); return $array[0]; } $array = ['name' => '张三', 'gender' => '男', 'age' => 18]; //========== 直接保存数组 ==========// $redis->set('array', $array, 3600); var_dump($redis->get('array')); // string(5) "Array" //========== 直接保存整数 ==========// $redis->set('int', 9527, 3600); var_dump($redis->get('int')); // string(4) "9527" //========== 直接保存浮点数 ==========// $redis->set('float', 3.14, 3600); var_dump($redis->get('float')); // string(4) "3.14" //========== 直接保存false ==========// $redis->set('true', true, 3600); var_dump($redis->get('true')); // string(1) "1" //========== 直接保存false ==========// $redis->set('false', false, 3600); var_dump($redis->get('false')); // string(0) "" //========== 直接保存null ==========// $redis->set('null', null, 3600); var_dump($redis->get('null')); // string(0) "" set_cache('array', $array, 3600); var_dump(get_cache('array')); // array(3) { ["name"]=> string(6) "张三" ["gender"]=> string(3) "男" ["age"]=> int(18) } set_cache('int', 9527, 3600); var_dump(get_cache('int')); // int(9527) set_cache('float', 3.14, 3600); var_dump(get_cache('float')); // float(3.14) set_cache('true', true, 3600); var_dump(get_cache('true')); // bool(true) set_cache('false', false, 3600); var_dump(get_cache('false')); // bool(false) set_cache('null', null, 3600); var_dump(get_cache('null')); // NULL //========== 总结 ==========// // 1、Redis只能保存字符串,如果直接将非字符串数据保存进去,那么取出数据时会变成字符串,尤其是数组,所有key/value内容都会丢失。 // 2、由于Redis只能保存字符串,所以想保存非字符串数据就必须对VALUE进行编码转成字符串,而最佳实现方式就是把VALUE作为数组元素, // 构造一个数组并对数组进行JSON编码,这样不仅仅是数组,其它如int、float、bool等类型数据也能保存,并且在获取VALUE时不会丢失 // VALUE的数据类型信息。 // 3、需要注意的是如果指定的缓存KEY不存在Redis::get()会返回false,这时如果缓存数据本身就是false就会有歧义,这种情况可根据实际 // 需求制定规则,例如不允许缓存null但允许缓存false,如果缓存不存在则返回null。(PS:可用Redis::exists()判断缓存是否存在)
<?php declare(strict_types=1); namespace MaNong; // 自定义类的类名也是Redis,所以需要给PHP扩展的Redis类设置别名 use Redis as PHPRedis; use JsonException; use RedisException; use function is_array; use function is_string; ini_set('display_errors', 'On'); error_reporting(-1); /** * Redis类(单例模式) */ class Redis { private ?PHPRedis $redis = null; // Redis实例(PHP扩展) private static ?Redis $instance = null; // Redis实例(自定义Redis类,非PHP扩展的Redis类) /** * 将构造方法声明为private防止通过new关键字创建实例 */ private function __construct() { } /** * 将克隆方法声明为private防止复制实例 */ private function __clone() { } /** * 设置缓存 * * @param string $key 缓存KEY * @param mixed $value 缓存VALUE,除了resource类型之外,可以为任何数据类型 * @param int $timeout 有效时间,单位为秒,若设为0则永久有效 * @return bool true=设置缓存成功|false=设置缓存失败 */ public static function set(string $key, mixed $value, int $timeout): bool { // 本方法规定有效时间为0表示永久有效,但Redis规定null才是永久有效,所以需要处理一下 $expire = $timeout > 0 ? $timeout : null; // Redis的缓存VALUE只能为string类型,所以需要先编码再保存 $json = self::encode($value); return is_string($json) && self::getInstance()->redis->set($key, $json, $expire); } /** * 获取缓存 * * @param string $key 缓存KEY * @return mixed 缓存VALUE(设置缓存时是什么类型,获取到的就是什么类型),若缓存不存在则返回null */ public static function get(string $key): mixed { $value = null; $json = self::getInstance()->redis->get($key); if (is_string($json)) { $array = self::decode($json); if (is_array($array) && isset($array[0])) { $value = $array[0]; } } return $value; } /** * 获取本类实例 * * @return Redis 本类实例(自定义Redis类,非PHP扩展的Redis类) */ private static function getInstance(): Redis { if (self::$instance === null) { self::$instance = new self(); self::$instance->redis = new PHPRedis(); try { $connect = self::$instance->redis->connect('localhost'); } catch (RedisException $e) { exit('Redis服务器连接失败:' . $e->getMessage()); } try { $auth = self::$instance->redis->auth('************'); } catch (RedisException $e) { exit('Redis服务器认证失败:' . $e->getMessage()); } if (!$connect || !$auth) { exit('Redis服务器连接(或认证)失败'); } } return self::$instance; } /** * 对变量进行JSON编码 * * @param mixed $value 待编码的value,除了resource类型之外,可以为任何数据类型 * @return string|false 成功则返回JSON编码的string或者在失败时返回false */ private static function encode(mixed $value): string|false { $encode = false; try { $encode = json_encode([$value], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } catch (JsonException $e) { unset($e); } return $encode; } /** * 对JSON格式的字符串进行解码 * * @param string $json 待解码的json string格式的字符串 * @return mixed 返回编码的数据,若解码失败将会返回null */ private static function decode(string $json): mixed { $decode = null; try { $decode = json_decode($json, true, 512, JSON_THROW_ON_ERROR); } catch (JsonException $e) { unset($e); } return $decode; } } /** * 打印变量的相关信息 * * @param mixed $value 要打印的表达式 * @param mixed ...$values 更多要打印的表达式 * @return void echo */ function v(mixed $value, mixed ...$values): void { ob_start(); // 打开输出控制缓冲 var_dump($value); echo ob_get_clean(); // 从缓冲区获取var_dump()的内容,然后清空缓冲区 foreach ($values as $v) { v($v); // 递归 } } // 测试用的缓存KEY和缓存VALUE $key = 'profile'; $value = ['name' => '张三', 'gender' => '男', 'birth' => 2003]; // 设置缓存 $ok = Redis::set($key, $value, 0); echo '设置缓存' . ($ok ? '成功' : '失败') . PHP_EOL; // 设置缓存成功 // 获取缓存 $profile = Redis::get($key . ''); v($profile); // array(3) { ["name"]=> string(6) "张三" ["gender"]=> string(3) "男" ["birth"]=> int(2003) }
Copyright © 2024 码农人生. All Rights Reserved