對一些高頻資料,我們都需要快取起來,以免 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 協議》,轉載必須註明作者和本文連結