
本文介绍如何在 modx 中通过 json 序列化与缓存管理器(cachemanager)持久化存储数组数据,实现跨片段(snippet)共享、按需加载与自动过期回源,避免高频重复执行耗时逻辑。
本文介绍如何在 modx 中通过 json 序列化与缓存管理器(cachemanager)持久化存储数组数据,实现跨片段(snippet)共享、按需加载与自动过期回源,避免高频重复执行耗时逻辑。
在 ModX 开发中,常遇到这样的场景:一个耗时较长的 Snippet(如从远程 API 获取顶级域名列表、解析大型配置文件等)需每周仅运行一次,但其生成的数组结果需被多个其他 Snippet(尤其是已启用缓存的)安全复用。由于 ModX 的缓存机制默认不支持直接缓存 PHP 数组(仅缓存字符串),若强行对原始数组调用 set(),将触发序列化异常或不可预测行为。因此,JSON 编码 + cacheManager 是最轻量、兼容性最佳的解决方案。
✅ 正确缓存数组:编码写入
首先,在“源头” Snippet(例如 tld_array)中生成数组后,将其 JSON 编码并写入缓存,设置 1 周(604800 秒)有效期:
// 示例:生成 $tldlist 数组后
$tldlist = ['com', 'org', 'net', 'cn', 'jp', 'de']; // 实际中可能来自 file_get_contents() 或 cURL
// 编码为 JSON 字符串并缓存(有效期 7 天)
$modx->cacheManager->set('tld_list_cache', json_encode($tldlist), 604800);
return json_encode($tldlist); // 可选:作为 Snippet 返回值用于调试⚠️ 注意:
set()第二个参数必须是字符串,json_encode()确保数组被安全转换;避免使用serialize(),因其依赖 PHP 版本且不易跨环境调试。
✅ 安全读取缓存:解码 + 回源兜底
在其他 Snippet(包括已启用缓存的)中,应始终采用「先查缓存、空则重建」策略,确保高可用性:
// 尝试从缓存读取
$cachedJson = $modx->cacheManager->get('tld_list_cache');
// 检查是否命中缓存且非空
if ($cachedJson !== null && is_string($cachedJson) && trim($cachedJson) !== '') {
$tldArray = json_decode($cachedJson, true); // true → 关联数组(非对象)
if (json_last_error() !== JSON_ERROR_NONE) {
$modx->log(modX::LOG_LEVEL_ERROR, 'Failed to decode cached tld_list_cache: ' . json_last_error_msg());
$tldArray = []; // 降级为空数组
}
} else {
// 缓存未命中或损坏:调用源头 Snippet 重建(此调用本身不缓存,故无副作用)
$tldArray = $modx->runSnippet('tld_array'); // 注意:该 Snippet 必须返回 JSON 字符串或可转数组的格式
if (is_string($tldArray)) {
$tldArray = json_decode($tldArray, true);
}
// 重建后立即写入缓存,供后续请求使用
if (is_array($tldArray) && !empty($tldArray)) {
$modx->cacheManager->set('tld_list_cache', json_encode($tldArray), 604800);
}
}? 关键注意事项
-
缓存键名唯一性:确保
'tld_list_cache'等键名全局唯一,避免与其他插件冲突; -
错误处理不可省略:
json_decode()后务必检查json_last_error(),防止因缓存损坏导致空数组静默失败; -
源头 Snippet 设计:被
runSnippet()调用的tld_array应明确返回 JSON 字符串(而非直接return $array),否则json_decode()会失败; -
清理维护:可通过
$modx->cacheManager->delete('tld_list_cache')手动清除旧缓存,或利用 ModX 后台「系统 → 清理缓存」批量操作; - 性能提示:对于超大数组(>1MB),建议启用 Memcached/Redis 缓存驱动以提升 I/O 效率。
通过这一模式,你既能满足「每周仅执行一次重逻辑」的业务约束,又能保障所有缓存型 Snippet 零延迟获取最新数据——真正实现高性能与低耦合的统一。

















