Dcat Admin 自定义 Form 表单—将配置内容缓存到 Redis 并统一调用
上一篇主要讲系统配置 Form 表单如何自定义,以及配置的 Form 表单扩展的问题。虽然功能已经满足使用,但也有其弊端:
- 系统配置是存在数据库中,且配置内容改动次数较少,每次获取仍需要查库,在大量用到配置的场景下影响性能。
- 没有统一的获取配置数据的接口,后期维护麻烦。
针对以问题我们的对策是
- 将配置缓存起来,使用 Redis 缓存。(当然用文件缓存也是 ok 的,但 Redis 应用的场景更多!)
- 统一系统配置调用的接口。
首先看一下配置表的迁移文件和数据
很简单,除了主键外,只剩下 name 和 value 两个有效字段。
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateSystemConfigsTable extends Migration { public function up() { Schema::create('system_configs', function (Blueprint $table) { $table->id(); $table->string('name'); $table->text('value'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('system_configs'); } }
数据库表存入的记录(现在只有两行记录,不过可以通过扩展 Tab 栏增加系统配置,就能增加表记录行数)
看第一行
name = config_one
数据的value
字段内容以及格式(json 格式)。
然后是 Redis 的配置
- .env 文件的配置
REDIS_CLIENT=phpredis REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379
- databse.php 的配置
'cache' => [ 'url' => env('REDIS_URL'), 'host' => env('REDIS_HOST', '127.0.0.1'), 'password' => env('REDIS_PASSWORD', null), 'port' => env('REDIS_PORT', '6379'), 'database' => env('REDIS_CACHE_DB', '1'), ],
- redis 的调用方法
# get 方法: Redis::connection('cache')->get($cacheKey); # set 方法: Redis::connection('cache')->set($cacheKey, json_encode($data)); # del 方法: Redis::connection('cache')->del($cacheKey);
最后是系统配置的统一接口以及调用方法
系统配置的统一接口
<?php namespace App\Models; use Eloquent; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Carbon; use Exception; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Redis; class SystemConfig extends Model { use HasFactory; const CACHE_KEY_PREFIX = 'System-Config'; protected $table = 'system_configs'; protected $fillable = ['name', 'value']; // 获取系统配置 public static function get($name, $key = null, $default = null) { if (empty($name)) { throw new Exception('配置名为空,请联系管理员'); } $cacheKey = self::CACHE_KEY_PREFIX; $jsonData = Redis::connection('cache')->get($cacheKey); $data = json_decode($jsonData, true); // 如果缓存没有数据 if (empty($data) || !is_array($data) || !Arr::exists($data, $name)) { $data = []; $config = self::query()->get()->toArray(); foreach ($config as $item) { $data[$item['name']] = json_decode($item['value'], true); } Redis::connection('cache')->set($cacheKey, json_encode($data)); } // 如果 name 不存在,直接返回 null if (!Arr::exists($data, $name)) { return null; } // 获取 name 对应的配置 $value = Arr::get($data, $name, $default); // 如果 key 值不存在,直接返回 name 对应的配置 if (!$key) { return $value; } // 如果 key 值存在,返回 name 对应配置中的 key 键对应的值 return Arr::get(Arr::get($data, $name, $default), $key, $default); } }
系统配置的调用示例:
// 获取整条配置信息 SystemConfig::get('config_one'); // 获取整条配置信息中的一个配置项 SystemConfig::get('config_one', 'email'); // 获取整条配置信息中的一个配置项,如果没有返回默认值 SystemConfig::get('config_one', 'email', 'mail.qq.com');
但是配置仍会改动,所以在必要时清除缓存
- 一般系统配置没有删除操作,只有创建和更新,现在只针对更新删除缓存。我没有用模型监听事件,我采用的是模型事件的闭包,请参见 模型闭包的使用
/** * 使用模型的闭包删除缓存 */ protected static function booted() { // 数据更新后 - 删除缓存 static::updated(function ($config) { $cacheKey = self::CACHE_KEY_PREFIX; Redis::connection('cache')->del($cacheKey); }); }
- 这样一来,在模型数据更新的时候,缓存是被清理掉的。
结语
- 好了,本节内容已经讲完,也不是很复杂,只用到了 Redis 的
String
数据结构,也没有什么高深的方法,简单的get
、set
和del
方法就满足了使用。 - 如果有更好的办法,欢迎在评论区讨论。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: