Cache::get() 默认不抛异常,需启用Redis驱动的'exception'=>true选项并用Cache::store('redis')->get()触发,捕获Throwable或RedisException,配合日志与探活机制实现可靠异常处理。

Cache::get() 抛出的异常类型不是 Exception,而是 Throwable
ThinkPHP 6.x 的缓存驱动(如 Redis、File)在连接失败或读写异常时,Cache::get() 或 cache() 函数默认不会抛出 Exception,而是直接返回 null 或触发 PHP 警告(E_WARNING),尤其在 File 驱动权限不足、Redis 连接超时未设异常模式时。你不能靠 try-catch Exception 捕获它。
真正能捕获底层错误的方式是启用驱动的异常模式:
- Redis 驱动需在
config/cache.php中显式开启:'options' => ['exception' => true] - File 驱动本身不支持异常抛出,只能靠前置检查:
is_writable(runtime_path() . 'cache/') - 所有驱动下,
Cache::has()和Cache::get()均不主动 throw,必须手动校验返回值 + 日志兜底
如何让缓存失败时抛出可捕获的异常
想统一用 try-catch 处理缓存异常,就得让底层驱动“说话”。Redis 是唯一支持原生异常的常用驱动,但默认关闭:
- 确认
config/cache.php中 Redis 缓存配置含'options' => ['exception' => true] - 不要依赖
Cache::get('key')抛异常——它仍返回null;改用Cache::store('redis')->get('key')才触发异常模式 - catch 时需兼容
Throwable(PHP 7+),因为 Redis 扩展抛的是RedisException,非Exception子类 - 示例:
try { $value = Cache::store('redis')->get('user:123'); } catch (RedisException $e) { Log::error('Redis cache failed', ['msg' => $e->getMessage()]); $value = null; } catch (Throwable $e) { Log::error('Cache unknown error', ['class' => get_class($e)]); $value = null; }
缓存连接失败却没报错?先查日志和 debug 级别
很多“连接失败无提示”实际是日志被吞了。ThinkPHP 的缓存驱动在静默失败时,只在 debug 模式且开启缓存日志后才记录细节:
立即学习“PHP免费学习笔记(深入)”;
- 确保
config/cache.php含'logger' => 'cache' - 在
config/log.php中配好'cache'通道,且'level' => 'debug' - 检查
runtime/log/cache/目录是否可写,否则日志根本落盘失败 - APP_DEBUG=true 时,部分驱动(如 File)会跳过写入逻辑,导致你以为“连上了”,其实压根没存 —— 必须关掉调试模式复现
自定义缓存异常类并全局拦截
框架不提供缓存专用异常类,但你可以封装一层,在业务关键路径强制兜底:
- 定义
app/exception/CacheException.php,继承RuntimeException - 写个工具方法,比如
safeCacheGet($key, $default = null),内部做连接探测 + 异常转译 - 对 Redis,先用
(new Redis())->connect()快速探活,失败则 throwCacheException - 避免在中间件或构造函数里调用缓存——那里的异常可能无法被捕获,应放在控制器或 service 层显式处理
null 像个温柔的陷阱,日志开关关着像一层黑布,APP_DEBUG=true 又悄悄禁用写入。真正的处理起点,永远是先让失败“发出声音”。



















