缓存与主题:对象缓存、页面缓存

作者: admin 分类: wordpress主题制作教程 发布时间: 2026-11-06 18:53

改了代码,页面没变

这个场景我遇到过不止一次:改完 functions.php,刷新页面,还是老样子。再刷,还是老样子。开始怀疑自己是不是改错了文件、是不是没保存、是不是改的那个是备份。

最后发现是缓存。改的代码是对的,只是没被执行。

这件事的要害不是”记得清缓存”,而是要理解:缓存把”每次请求都跑一遍 PHP”变成了”直接吐一份 HTML”。 你的模板代码压根没运行。

三层缓存,各管一段

先分清层次,不然永远在瞎清。

层 存在哪 管什么 怎么清
浏览器缓存 访客的电脑/手机 CSS、JS、图片 访客自己 Ctrl+F5
页面缓存 服务器磁盘 整页 HTML 插件里点”清空所有缓存”
对象缓存 内存(Redis/Memcached) 数据库查询结果 重启服务或清 key

我改完代码看不到效果,99% 是页面缓存。因为我改的是 PHP,而页面缓存里存的是一份已经渲染好的 HTML——它不会因为你改了 PHP 就自动失效。

页面缓存和主题的冲突点

这里有个概念必须先建立:

页面缓存生效时,你的 header.php、single.php、functions.php 一行都不会执行。

不是”执行了但没效果”,是根本不执行。服务器直接找到那份 HTML 文件,发出去,完事。

所以,凡是”每次请求都该不一样”的逻辑,放在模板里就是错的。举几个例子:

  • is_user_logged_in() 判断显示”你好,某某”——缓存后,未登录的访客会看到别人的名字;
  • 按访问时间显示”现在是下午好”——所有人看到的都是生成缓存那一刻的问候;
  • 随机推荐几篇文章——永远是同一批;
  • 购物车数量、未读消息数——全是死的。

这些不是”缓存插件的 bug”,是主题的写法跟缓存机制冲突了。

正确的做法:告诉缓存”这页别存”

WordPress 有个标准常量,缓存插件都认:

define( 'DONOTCACHEPAGE', true );

在需要动态输出的页面里定义它,页面缓存插件就会跳过这一页。

典型用法是挂在 template_redirect 上(这时已经知道是哪个页面了,但还没开始输出):

add_action( 'template_redirect', function () {
    if ( is_user_logged_in() ) {
        define( 'DONOTCACHEPAGE', true );
    }
} );

这句话的意思是:登录用户看到的页面,永远不缓存。 访客看到的照常缓存,两边都合理。

另一条路是把动态部分挪走:页面主体照常缓存,那几块”会变”的内容用 AJAX 单独请求。这是大型站点的标准做法,但复杂度高一个量级,小站不值得。

我踩过的那个坑:sitemap 被缓存成 HTML

这个案例值得单独讲,因为它暴露了”缓存插件不认识非 HTML 内容”这个问题。

WordPress 自带一个站点地图 /wp-sitemap.xml。它由 PHP 动态生成,正常情况下响应头是:

Content-Type: application/xml

但我这边实测是:

Content-Type: text/html

结果就是:浏览器打开那个地址,看到的是一片空白。因为浏览器拿到”XML 内容 + HTML 身份”,按 HTML 去解析,把 <?xml 当成看不懂的注释直接跳过,后面整段全忽略。

我一开始以为是文件坏了,反复清缓存、反复刷,没用。后来加了个随机参数绕开缓存,立刻正常:

https://www.caogenbj.com/wp-sitemap.xml?abc=123

这一个测试就把问题定性了:不是内容错,是缓存层把响应头写死了。

为什么?因为页面缓存插件的设计目标是”缓存 HTML 页面”。它抓到一份响应,按 HTML 存下来,再吐出去的时候也按 HTML 标注。它不管你这个 URL 原本是什么类型。

解法有两个:

一、让插件别碰这个地址。在缓存插件的”永不缓存以下页面”里填:

wp-sitemap

二、在主题里定义常量。如果你能改到主题,更彻底:

if ( isset( $_SERVER['REQUEST_URI'] )
     && strpos( $_SERVER['REQUEST_URI'], 'wp-sitemap' ) !== false ) {
    define( 'DONOTCACHEPAGE', true );
}

这段要放在 functions.php 最顶部,不要包进 add_action 里——因为缓存插件判断”要不要缓存”的时间点很早,你得赶在它前面。

对象缓存:主题基本不用管,但要知道它在

对象缓存缓存的是”数据库查询结果”。比如 get_option() 查一次,结果存内存,下次直接从内存拿。

对主题作者来说,能用上的场景不多。但有一个原则要遵守:

别在模板里写”每次都重新查库”的代码。

比如我在卷一讲过的:为了在一个页面上取两次同样的数据,用两次 WP_Query。第二次完全可以复用第一次的结果。对象缓存能救一部分,但它不是免费的。

清缓存的正确姿势

第一种情况:改的是 PHP。清页面缓存就行,插件后台那个”清空所有缓存”的大按钮。

第二种情况:改的是 CSS/JS。清完页面缓存还不够,因为访客浏览器里那份旧的还在。这时候要在文件地址后面带版本号,WordPress 的 wp_enqueue_style 第四个参数就是干这个的:

wp_enqueue_style( 'my-style', get_stylesheet_uri(), array(), '1.0.3' );

改一次样式,把 1.0.3 改成 1.0.4,浏览器就会当成新文件重新下载。这比让访客按 Ctrl+F5 靠谱得多,因为他不会按。

第三种情况:改完还是不对。加个随机参数试试(?nc=123)。能正常就说明是缓存,不能正常才是代码问题。

这个”加参数”的动作,是我排查缓存问题的第一招,几乎每次都灵。

小结

一句话记住:页面缓存生效时,你的 PHP 一行都不跑。所以”每次都该变”的东西不能写在模板里;改完看不到效果,先加参数验证是不是缓存。

下一篇聊多语言——不是为了翻译,是为了把散落各处的文字收拢到一处。

本系列导航

相关文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Powered by 草根站长笔记 © 2015-2026 草根站长笔记 Inc.版权所有,禁止转载