
本文介绍在 MODX 中跨片段(Snippet)共享高频生成、低频更新的数组数据的实践方案:通过 cacheManager 将 PHP 数组序列化为 JSON 字符串进行持久化缓存,并支持自动失效回退与按需重建,确保性能与一致性兼顾。
本文介绍在 modx 中跨片段(snippet)共享高频生成、低频更新的数组数据的实践方案:通过 `cachemanager` 将 php 数组序列化为 json 字符串进行持久化缓存,并支持自动失效回退与按需重建,确保性能与一致性兼顾。
在 MODX 开发中,常遇到一类典型场景:一个片段(如 tld_array)负责生成结构化数据(例如域名后缀列表),该操作开销较大(含远程请求、数据库聚合或复杂计算),因此需启用缓存;而另一个片段必须以 uncached 方式运行(例如用于动态表单渲染或实时权限校验),却仍需访问同一份数据。此时直接调用带缓存的片段会导致缓存失效或逻辑冲突,而重复执行原始生成逻辑又违背性能初衷。
理想的解决方案是绕过片段缓存机制,直接操作底层缓存系统,将数组作为独立缓存项进行管理。MODX 的 cacheManager 提供了灵活的键值存储能力,配合 JSON 序列化即可安全持久化 PHP 数组:
// 在生成型片段(如 tld_array)中:生成并缓存数组(有效期 1 周 = 604800 秒)
$tldlist = ['com', 'org', 'net', 'dev', 'xyz']; // 示例数据
$modx->cacheManager->set('tld_list_cache', json_encode($tldlist), 604800);
return json_encode($tldlist); // 可选:返回供当前调用使用在 uncached 片段中,通过缓存键读取并反序列化:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
// 尝试从缓存获取
$cachedJson = $modx->cacheManager->get('tld_list_cache');
$tldarray = $cachedJson ? json_decode($cachedJson, true) : null;
// 若缓存未命中(NULL 或空),触发重建逻辑
if ($tldarray === null) {
$tldarray = $modx->runSnippet('tld_array'); // 调用原始生成片段
// 注意:此处 tld_array 应确保返回纯数组或已 JSON 编码的字符串
if (is_string($tldarray) && !empty($tldarray)) {
$tldarray = json_decode($tldarray, true);
}
// 重建后立即写入缓存,避免后续请求重复生成
if (is_array($tldarray)) {
$modx->cacheManager->set('tld_list_cache', json_encode($tldarray), 604800);
}
}
// 此时 $tldarray 即为可用的 PHP 关联/索引数组
foreach ($tldarray as $tld) {
echo '<option value="' . $modx->sanitizeHTML($tld) . '">' . $tld . '</option>';
}关键注意事项:
- ✅ 始终使用
json_encode($array, JSON_UNESCAPED_UNICODE)(若含中文等 Unicode 字符)并配对json_decode($json, true)确保返回关联数组; - ✅ 缓存键名应全局唯一且语义清晰(如
tld_list_cache),避免与其他组件冲突; - ⚠️
runSnippet('tld_array')的返回值需明确处理:若原片段已返回 JSON 字符串,则直接解码;若返回原生数组,需先编码再缓存; - ? 建议在
tld_array片段内部也加入缓存存在性检查,形成双重保障; - ? 定期清理过期缓存(MODX 自动处理),但可结合
cacheManager->delete()手动刷新特定键(如运维触发更新)。
该模式解耦了缓存策略与片段执行逻辑,既满足 uncached 片段的实时性要求,又规避了高频重复计算,是 MODX 高级缓存实践中的推荐范式。

















