avatar

mdo

Hello

  • 首页
  • 知识库
  • 归档
  • 标签
  • 关于
主页 think-orm 2.0.62 单独设置数据表字段缓存驱动和数据缓存驱动
文章

think-orm 2.0.62 单独设置数据表字段缓存驱动和数据缓存驱动

发表于 18天前 更新于 18天前
作者 mdo
8~11 分钟 阅读

think-cache 拥有强大的多通道(Multi-store)管理能力,但问题的根源在于 think-orm 底层的调用机制太死板。即使您在 think-cache 中配置了 file 和 redis 两个完全独立的通道,think-orm 默认也只会向您通过 Db::setCache() 注入的那个“主通道”发送所有缓存请求。

要真正实现数据缓存(Data Cache)与数据表字段缓存(Schema/Fields Cache)的驱动分离管理,有以下两种最佳实践方案:


方案一:配合 think-cache 自定义代理驱动(最彻底、支持常驻内存)

这是利用 think-cache 解决该问题最标准的方式。我们可以自定义一个代理类,它同样实现 Psr\SimpleCache\CacheInterface 规范。当 think-orm 调用它时,它会根据缓存键名(Key)的特征,自动将请求分流到 think-cache 的不同通道。

Step 1: 创建缓存分流代理类

在项目中新建一个代理类,例如 app\common\OrmCacheProxy.php:

namespace app\common;

use Psr\SimpleCache\CacheInterface;
use think\facade\Cache;

class OrmCacheProxy implements CacheInterface
{
    // 获取实际的 think-cache 驱动通道
    protected function getDriver(string $key)
    {
        // think-orm 2.0 字段缓存的 key 默认带有数据库名或表名标识(如 schema:xxx 或特定 md5 格式)
        // 如果想把字段缓存存文件(file),常规数据缓存存Redis
        if (str_contains($key, 'schema') || str_contains($key, 'fields')) {
            return Cache::store('file'); // 切换到 think-cache 的 file 通道
        }

        return Cache::store('redis'); // 默认数据缓存走 redis 通道
    }

    public function get($key, $default = null) {
        return $this->getDriver($key)->get($key, $default);
    }

    public function set($key, $value, $ttl = null) {
        return $this->getDriver($key)->set($key, $value, $ttl);
    }

    public function delete($key) {
        return $this->getDriver($key)->delete($key);
    }

    public function clear() {
        // 清理时需要同时清理两边
        Cache::store('file')->clear();
        return Cache::store('redis')->clear();
    }

    public function getMultiple($keys, $default = null) {
        // 简单处理,直接循环
        $result = [];
        foreach ($keys as $key) { $result[$key] = $this->get($key, $default); }
        return $result;
    }

    public function setMultiple($values, $ttl = null) {
        foreach ($values as $key => $value) { $this->set($key, $value, $ttl); }
        return true;
    }

    public function deleteMultiple($keys) {
        foreach ($keys as $key) { $this->delete($key); }
        return true;
    }

    public function has($key) {
        return $this->getDriver($key)->has($key);
    }
}

Step 2: 在全局初始化时注入此代理

在应用启动或中间件中(如 Webman 的 bootstrap.php 或 ThinkPHP 的 service.php),将这个代理实例注入给 Db:

use think\facade\Db;
use app\common\OrmCacheProxy;

// 注入自定义的分流代理
Db::setCache(new OrmCacheProxy());

方案二:利用底层扩展参数,强制隔离(最原生、无代码污染)

如果您只想把数据表字段缓存存在本地文件,而数据缓存(->cache())存在 Redis,其实可以绕过 Db::setCache() 的限制。

think-orm 内置了一个完全独立于 Db::setCache() 的文件字段缓存路径参数:schema_cache_path。

在您的 database.php 或 think-orm.php 配置文件中,直接进行如下配置:

return [
    // ... 其它连接配置
    'fields_cache'      => true, // 开启字段缓存
    // 关键点:直接通过目录指定,ORM 底层会强制使用原生 File 写入该目录,不走全局 Cache 驱动
    'schema_cache_path' => runtime_path() . 'schema' . DIRECTORY_SEPARATOR, 
];

接着,您只需要把全局的 Db::setCache() 设置为您需要的 Redis 驱动:

use think\facade\Db;
use think\facade\Cache;

// 全局只管数据查询缓存,全部注入为 Redis 通道
Db::setCache(Cache::store('redis')); 

为什么这个方案能生效?
当 schema_cache_path 被配置了有效路径时,think-orm 底层的 Schema 类在读取表结构时,会优先使用内部的物理文件读写逻辑,从而和通过 Db::setCache() 传入的查询数据缓存驱动完全剥离开。


请问您目前使用的是方案二这种“字段存本地文件、数据存 Redis”的典型场景吗?如果仍需要更复杂的隔离(比如字段存 Memcached,数据存 Redis),我们可以继续完善方案一的代理规则。

知识库
数据表 驱动 缓存
许可协议:  CC BY 4.0
分享

相关文章

7月 21, 2026

think-orm 2.0.62 单独设置数据表字段缓存驱动和数据缓存驱动

think-cache 拥有强大的多通道(Multi-store)管理能力,但问题的根源在于 think-orm 底层的调用机制太死板。即使您在 think-cache 中配置了 file 和 redis 两个完全独立的通道,think-orm 默认也只会向您通过 Db::setCache() 注入

7月 1, 2026

WebSocket Server + 独立 RPC Server

从架构角度来说,它已经接近 think-swoole 能做到的极限了,但是我仍然不建议继续这样维护。 原因不是代码写法,而是 think-swoole 本身的事件模型。 第一处问题:addListener() 仍然共享 Worker 你的代码: $rpcServer = $server->addLi

6月 25, 2026

Linux | Reqable · API抓包调试 + API测试一站式工具

Reqable是什么? Reqable = Fiddler + Charles + Postman 极简的设计、极高的性能、丰富的功能、桌面手机多端平台。 多协议流量分析 基于经典的MITM中间人代理方案捕获和分析您的应用流量,自适应HTTP/HTTPS/SOCKS4/SOCKS5等多种代理协议,并

下一篇

WebSocket Server + 独立 RPC Server

上一篇

AI 驱动型 Facebook 群组关键词监控 Chrome 浏览器插件

最近更新

  • 完美地解决 TP3 老系统数据的平滑读取
  • thinkphp3 redis序列化和反序列化
  • Table 空间极易发生哈希冲突并溢出
  • 将监控程序直接跑在云端
  • AI 驱动型 Facebook 群组关键词监控 Chrome 浏览器插件

热门标签

API CodeGeex Gitkraken Management Manticore Premiere Sublime Swoole ThinkPHP ThinkPHP5

目录

©2026 mdo. 保留部分权利。