* +---------------------------------------------------------------------- */ namespace crmeb\traits\dao; use crmeb\services\CacheService; use crmeb\utils\Tag; use think\cache\TagSet; use think\Container; use think\facade\Log; use think\Model; /** * Trait CacheDaoTrait * @package crmeb\traits\dao * @method Model getModel() * @method Model getPk() */ trait CacheDaoTrait { /** * 获取redis * @return \Redis * @author 等风来 * @email 136327134@qq.com * @date 2022/10/29 */ private function getRedisConnect() { return CacheService::redisHandler()->handler(); } /** * 获取缓存 * @return TagSet|\think\facade\Cache * @author 等风来 * @email 136327134@qq.com * @date 2022/11/10 */ private function getCacheHander() { return CacheService::redisHandler(); } /** * 对外开放方法 * @return TagSet|\think\facade\Cache * @author 等风来 * @email 136327134@qq.com * @date 2022/11/10 */ public function cacheHander() { return $this->getCacheHander(); } /** * 缓存标签 * @param null $tag * @return Tag * @author 等风来 * @email 136327134@qq.com * @date 2022/11/10 */ public function cacheTag($tag = null) { $key = $this->cacheKey() . 'tag'; $tag = $tag ? $key . ':' . $tag : $key; $redis = CacheService::redisHandler($tag); return new Tag($redis, $tag); } /** * 总缓存数据量 * @return mixed */ public function cacheCount() { $cacheKey = $this->cacheKey(); $rds = $this->getRedisConnect(); return $rds->hLen($cacheKey . 'map'); } /** * 读取缓存全部数据 * @return mixed */ public function cacheList(string $key = '') { $cacheKey = $this->cacheKey() . $key; $rds = $this->getRedisConnect(); $map = $rds->hGetAll($cacheKey . 'map'); //key排序 ksort($map); $list = array_values($map) ?: []; foreach ($list as $key => $item) { $list[$key] = $this->unserialize($item); } return $list; } /** * 读取缓存分页数据 * @param int $page * @param int $limit * @param string $key * @return array */ public function cachePageData(int $page = 1, int $limit = 10, string $key = '') { $cacheKey = $this->cacheKey() . $key; $rds = $this->getRedisConnect(); $page = max($page, 1); $limit = max($limit, 1); //先读排序 $pageList = $rds->zRangeByScore($cacheKey . 'page', ($page - 1) * $limit, ($page * $limit) - 1); //再读数据 $list = $rds->hMGet($cacheKey . 'map', $pageList) ?: []; if (is_array($list)) { $newList = []; foreach ($list as $value) { $newList[] = $this->unserialize($value); } $list = $newList; } $count = $rds->hLen($cacheKey . 'map'); return compact('list', 'count'); } /** * 单个查询数据 * @param int|string $id * @return false|string|array */ public function cacheInfoById($id) { $cacheKey = $this->cacheKey(); $rds = $this->getRedisConnect(); $value = $rds->hGet($cacheKey . 'map', $id); return $value === null ? null : $this->unserialize($value); } /** * 批量查询数据 * @param $ids * @return mixed */ public function cacheInfoByIds(array $ids) { $cacheKey = $this->cacheKey(); $rds = $this->getRedisConnect(); $arr = $rds->hMGet($cacheKey . 'map', $ids); if (is_array($arr)) { $newList = []; foreach ($arr as $key => $value) { $arr[$key] = $this->unserialize($value); } $arr = $newList; } return $arr; } /** * 更新单个缓存 * @param $info * @return false|mixed */ public function cacheUpdate(array $info, $key = null) { $pk = $this->getPk(); if ((empty($info) || !isset($info[$pk])) && !$key) { return false; } $cacheKey = $this->cacheKey(); $rds = $this->getRedisConnect(); $key = $key ?: $info[$pk]; return $rds->hSet($cacheKey . 'map', $key, $this->serialize($info)); } /** * 序列化数据 * @param $value * @return string * @author 等风来 * @email 136327134@qq.com * @date 2022/11/10 */ private function serialize($value) { try { return serialize($value); } catch (\Throwable $e) { Log::error('序列化发生错误:' . $e->getMessage()); return $value; } } /** * 反序列化数据 * @param $value * @return mixed * @author 等风来 * @email 136327134@qq.com * @date 2022/11/10 */ private function unserialize($value) { try { return unserialize($value); } catch (\Throwable $e) { Log::error('反序列化发生错误:' . $e->getMessage()); return $value; } } /** * @param int $id * @param $field * @param null $value * @return false|mixed * @author 等风来 * @email 136327134@qq.com * @date 2022/11/1 */ public function cacheSaveValue(int $id, $field, $value = null) { $pk = $this->getPk(); $info = $this->cacheInfoById($id); if (!$info) { $newInfo = $this->get($id); $info = $newInfo ? $newInfo->toArray() : []; } if (is_array($field)) { foreach ($field as $k => $v) { $info[$k] = $v; } } else { $info[$field] = $value; } $info[$pk] = $id; return $this->cacheUpdate($info); } /** * 不存在则写入,存在则返回 * @param $key * @param callable|null $fn * @param null $default * @return array|false|mixed|string|null * @author 等风来 * @email 136327134@qq.com * @date 2022/11/1 */ public function cacheRemember($key, callable $fn = null, $default = null) { //不开启数据缓存直接返回 if (!app()->config->get('cache.is_data')) { if ($fn instanceof \Closure) { return Container::getInstance()->invokeFunction($fn); } else { return $default; } } $info = $this->cacheInfoById($key); if ((null === $info || false === $info) && is_callable($fn)) { //读取数据库缓存 $newInfo = $fn(); if (null !== $newInfo) { //缓存数据存在则更新 $this->cacheUpdate($newInfo, $key); } $info = $newInfo; } return null !== $info ? $info : $default; } /** * 批量更新缓存 * @param $list * @return false|mixed */ public function cacheUpdateList(array $list, string $key = '') { if (empty($list)) { return false; } $cacheKey = $this->cacheKey() . $key; $pk = $this->getPk(); $rds = $this->getRedisConnect(); $map = []; foreach ($list as $item) { if (empty($item) || !isset($item[$pk])) { continue; } $map[$item[$pk]] = $this->serialize($item); } return $rds->hMSet($cacheKey . 'map', $map); } /** * 删除单条缓存 * @param $id */ public function cacheDelById(int $id) { $cacheKey = $this->cacheKey(); $rds = $this->getRedisConnect(); $rds->hDel($cacheKey . 'map', $id); $rds->zRem($cacheKey . 'page', $id); } /** * 批量删除缓存 * @param $ids */ public function cacheDelByIds(array $ids) { $cacheKey = $this->cacheKey(); $rds = $this->getRedisConnect(); foreach ($ids as $id) { $rds->hDel($cacheKey . 'map', $id); $rds->zRem($cacheKey . 'page', $id); } } /** * 创建缓存 * @param array $list * @author 等风来 * @email 136327134@qq.com * @date 2022/10/29 */ public function cacheCreate(array $list, string $key = '') { $pk = $this->getPk(); $cacheKey = $this->cacheKey() . $key; $rds = $this->getRedisConnect(); //启动事务 $rds->multi(); //删除旧数据 $rds->del($cacheKey . 'map'); $rds->del($cacheKey . 'page'); //组合数据 $map = []; foreach ($list as $i => $item) { $map[$item[$pk]] = $item; //存zset 排序 $rds->zAdd($cacheKey . 'page', $i, $item[$pk]); } foreach ($map as $k => &$item) { $item = $this->serialize($item); } //存hmset 数据 $rds->hMSet($cacheKey . 'map', $map); //执行事务 $rds->exec(); } protected function cacheKey() { return 'mc:' . $this->getModel()->getName() . ':'; } /** * * @param $key * @return string * @author 等风来 * @email 136327134@qq.com * @date 2022/11/10 */ public function getCacheKey($key) { return $this->cacheKey() . $key; } /** * 更新缓存 * @param string $key * @param $value * @return bool * @author 等风来 * @email 136327134@qq.com * @date 2022/11/1 */ public function cacheStrUpdate(string $key, $value, int $expire = null) { return $this->getCacheHander()->set($this->cacheKey() . 'str:' . $key, $value, $expire); } /** * 获取缓存 * @param string $key * @return false|mixed|string * @author 等风来 * @email 136327134@qq.com * @date 2022/11/1 */ public function cacheStrGet(string $key) { return $this->getCacheHander()->get($this->cacheKey() . 'str:' . $key); } /** * 获取表缓存是否有数据 * @return false|mixed|string * @author 等风来 * @email 136327134@qq.com * @date 2022/11/1 */ public function cacheStrTable() { return $this->getRedisConnect()->get($this->cacheKey()); } /** * 设置表缓存是否有数据 * @param int $value * @return bool * @author 等风来 * @email 136327134@qq.com * @date 2022/11/1 */ public function cacheStrSetTable(int $value = 1) { return $this->getRedisConnect()->set($this->cacheKey(), $value); } /** * 删除缓存 * @param string $key * @return int * @author 等风来 * @email 136327134@qq.com * @date 2022/11/1 */ public function cacheStrDel(string $key) { return $this->getCacheHander()->delete($this->cacheKey() . 'str:' . $key); } /** * 获取缓存,没有则写入缓存并返回 * @param string $key * @param callable|null $fn * @param null $default * @return false|mixed|string|null * @author 等风来 * @email 136327134@qq.com * @date 2022/11/1 */ public function cacheStrRemember(string $key, callable $fn = null, int $expire = null, $default = null) { //不开启数据缓存直接返回 if (!app()->config->get('cache.is_data')) { if ($fn instanceof \Closure) { return Container::getInstance()->invokeFunction($fn); } else { return $default; } } $value = $this->cacheStrGet($key); if ((null === $value || false === $value) && is_callable($fn)) { $newValue = $fn(); if (null !== $newValue) { $this->cacheStrUpdate($key, $value, $expire); } $value = $newValue; } return null !== $value ? $value : $default; } }