avatar

mdo

Hello

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

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

发表于 2026-07-21 更新于 2026-07- 21
作者 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
分享

相关文章

10月 7, 2026

比尔盖茨的智慧:想多赚钱,就每天循环做这3件事

我们总有一种非常固执的错觉,认为那些站在财富金字塔顶端的人,必然拥有某种超越常人的特异功能。我们在脑海中给比尔盖茨这样的大佬描绘了一幅极其悲壮的奋斗画像。大家总觉得,他之所以能富可敌国,肯定是因为他每天只睡三个小时,同时对着八个电脑屏幕疯狂敲击键盘,每一秒钟都在做出价值几亿美金的生死抉择。 为了模仿

9月 28, 2026

程序员越想创业,越不要急着动手

一个能源方面的前辈找到我,希望通过我把一些人工的工作 AI 自动化。 能源方面我不懂,找 Gemini 聊完发现这个是可以复制的,非常兴奋。我跟老婆说,这个项目做好以后可以做成平台,推广到其他公司,你就等着做总裁夫人吧! 她听完以后跟我说,这个项目还是太定制化,和我之前做的一个项目很像。 那个项目一

9月 25, 2026

忍了一年多,我终于对i18n下手了过去一年,我主要参与国际机票业务的开发工作,因此每天都要和多语言(i18n)打交道

前言 大家好,我是奈德丽。 过去一年,我主要参与国际机票业务的开发工作,因此每天都要和多语言(i18n)打交道。熟悉我的朋友都知道,我这个人比较“惜力”(并不是,实际上只是忍不下去了),对于重复笨拙的工作非常抵触,于是,我开始思考如何优化团队的多语言管理模式。 痛点背景 先说说我们在机票项目中遇到的

下一篇

WebSocket Server + 独立 RPC Server

上一篇

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

最近更新

  • 比尔盖茨的智慧:想多赚钱,就每天循环做这3件事
  • iOS 侧载(Sideloading)工具
  • 程序员越想创业,越不要急着动手
  • 注册 Chat Participant
  • 中秋给在外游子的一封信

热门标签

API CodeGeex Coding Cursor DeepSeek Docker Gitkraken Harness Laravel Management

目录

©2026 mdo. 保留部分权利。