/**
* 服务工厂类
* 统一管理服务实例创建,实现单例模式,支持依赖注入
*/
class ServiceFactory
{
/**
* 服务实例缓存
*/
private static array $instances = [];
/**
* 获取缓存服务实例
*/
public static function getCacheService(
$redis = null,
string|null $prefix = null
): CacheService {
$key = 'CacheService';
if (!isset(self::$instances[$key])) {
self::$instances[$key] = new CacheService($redis, $prefix);
}
return self::$instances[$key];
}
}
/**
* 缓存服务
* 提供统一的缓存操作接口,封装Redis操作
*/
class CacheService
{
private $redis;
private $prefix;
public function __construct($redis = null, string|null $prefix = null)
{
$this->redis = $redis ?? Redis::connection('default');
$this->redis->select(getenv('redisDb'));
$this->prefix = $prefix;
}
public function rPush(string $key, string ...$values):int|bool
{
array_walk($values, function(&$value) {
$value = (string)$value;
});
$cacheKey = $this->prefix ? $this->prefix . $key : $key;
return $this->redis->rpush($cacheKey, ...$values);
}
public function get(string $key): ?string
{
$cacheKey = $this->prefix ? $this->prefix . $key : $key;
$value = $this->redis->get($cacheKey);
return $value === false ? null : $value;
}
}
// 伪代码A
$this->cacheService = ServiceFactory::getCacheService();
$cacheKey = 'key';
$this->cacheService->pipeline(); // 开启管道
foreach ($idMap as $id) {
$this->cacheService->rPush($cacheKey, $id);
}
$this->cacheService->exec(); // 提交
// 伪代码B
$this->cacheService = ServiceFactory::getCacheService();
$cacheKey = 'key';
$this->cacheService->get($cacheKey);
rPush定义了int|bool返回类型,在管道下返回的是redis对象报错
Return value must be of type int|bool, Redis returned
解决方法是立即去掉返回类型后重启
public function rPush(string $key, string ...$values)
这时问题2来了(🤦♀️)
TypeError: app\common\service\CacheService::get(): Return value must be of type ?string, Redis returned
(问号脸) (问号脸) (问号脸)
想到了问题1,马上去修改返回类型,又想到了get它怎么会有类型有问题(问号脸)
去看了一下伪代码1使用了管道,这个时候电话来了....一边对喷一边执行 php start.php stop
public function redis()
{
$connection = Redis::connection('default');
$connection->select(getenv('redisDb'));
return $connection;
}
public function get(string $key): ?string
{
$cacheKey = $this->prefix ? $this->prefix . $key : $key;
$value = $this->redis()->get($cacheKey);
return $value === false ? null : $value;
}
$this->redis()->get($cacheKey);
这样每次都是一个新的连接,然后把pipeline和exec方法删除
Ctrl+ H
$this->redis->
替换成
$this->redis()->
需要使用管道的地方
$this->cacheService = ServiceFactory::getCacheService();
$redis = $this->cacheService->redis();
$cacheKey = 'key';
$redis->pipeline(); // 开启管道
foreach ($idMap as $id) {
$redis->rPush($cacheKey, $id);
}
$redis->exec(); // 提交
思考了一会其实不改$this->redis添加redis()那个方法获取一个新的连接也行的
本帖纯属骗积分