可复用的缓存组件

对一些高频数据,我们都需要缓存起来,以免 MySQL 压力过大。
一般的写法是先判断缓存中是否有数据,没有数据再将数据查出来,再缓存起来。
其实可以用一个函数将这个过程封装起来
helper.php

if (!function_exists('remember')) {
    /**
     * 缓存数据
     *
     * @param $uniqId
     * @param $dataSource mixed|\Closure 数据来源
     * @param int $ttl
     * @return mixed|string
     */
    function remember($uniqId, $dataSource, int $ttl = 600)
    {
        $redisKey = 'remember:' . $uniqId;
        $result = Redis::get($redisKey);

        if ($result) {
            return unserialize($result);
        }

        if ($dataSource instanceof \Closure) {
            $result = $dataSource();
        } elseif (is_array($dataSource) && isset($dataSource[0]) && is_object($dataSource[0])) {
            $object = $dataSource[0];
            $function = $dataSource[1];
            $args = $dataSource[2] ?? [];
            $result = call_user_func_array([$object, $function], $args);
        } else {
            $result = $dataSource;
        }

        Redis::setex($redisKey, $ttl, serialize($result));
        return $result;
    }
}
if (!function_exists('forget')) {
  /**
 * 清除已缓存的数据
  *
 * @param $uniqId
  * @return int
 */  function forget($uniqId): int
  {
  $redisKey = 'remember:' . $uniqId;
 return Redis::del($redisKey);
  }
}

使用方法

$linkData = remember("player_link_data:{$gid}:{$uid}", function () use ($gid, $uid) {
                $player = Player::whereUid($uid)->whereGid($gid)->first();
                return [
                    'admin_id' => $player->admin_id,
                    'team_id' => $player->team_id,
                ];
            });

缓存对象执行某个方法后的结果

除了可以将回调函数的执行结果缓存,还可以将对象执行某个方法后的结果缓存起来
app/Services/Cache/CacheBase.php

<?php

namespace App\Services\Cache;

use Illuminate\Support\Arr;

abstract class CacheBase
{
    /**
     * 全部数据
     * @var array
     */
    protected array $all;

    /**
     * 缓存的唯一 id
     * @var string
     */
    protected string $uniqid;

    protected int $ttl = 600;

    /**
     * 获取全部数据
     * @return array
     */
    abstract protected function allData(): array;

    /**
     * 获取全部数据并缓存
     * @return mixed|string
     */
    public function all()
    {
        $all = remember($this->uniqid, [$this, 'allData'], $this->ttl);
        return $all;
    }

    /**
     * 清除数据缓存
     * @return int
     */
    public function clean()
    {
        return forget($this->uniqid);
    }

    public function get($key)
    {
        $all = $this->all();
        $result = $all[$key] ?? null;

        return $result;
    }

    public function only($keys)
    {
        $all = $this->all();
        $result = Arr::only($all, $keys);

        return $result;
    }

    public function __get($property)
    {
        if (!isset($this->all)) {
            $this->all = $this->all();
        }

        $result = $this->all[$property] ?? null;

        return $result;
    }
}

app/Services/Cache/User/BanIpList.php

<?php

namespace App\Services\Cache\User;

use App\Models\Config\BanIp;
use App\Services\Cache\CacheBase;

class BanIpList extends CacheBase
{
    protected string $uniqid;

    public function __construct()
    {
        $this->uniqid = 'BannedIp:';
    }

    public function allData(): array
    {
        return BanIp::where('release_time', '>', BanIp::raw('now()'))
            ->where('enable', '=', 1)
            ->pluck('ip')->toArray();
    }
}
use App\Services\Cache\User\BanIpList;

$banIPObj = new BanIpList();
$banIPList = $banIPObj->all();
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2
GDDD

看这标题,以为是讲缓存系统的😂

2年前 评论
liuyuit (楼主) 2年前

又开始造轮子了

$value = Cache::remember('users', $seconds, function () {
    return DB::table('users')->get();
});
2年前 评论
liuyuit (楼主) 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
1
粉丝
0
喜欢
1
收藏
2
排名:2650
访问:341
私信
所有博文
社区赞助商