搜索全站
主题 9 分钟阅读

主题更新前必做的三件事:备份、子主题检查、变更日志

主题更新不是点一下"现在更新"就完事。本文给出更新前三件事:可回滚备份、确认改动是否写在子主题、读懂变更日志,并附 6 个真实踩坑与命令行备份示例。

U
UFO_PF 2023-10-22 · 阅读 9 分钟
主题 主题
阅读提示
本文约 3,583 字,预计阅读 9 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:点了”现在更新”,首页直接白屏

后台「仪表盘 → 更新」里躺着一个红色数字,点「现在更新」,进度条走到一半卡住,刷新后台提示”致命错误”,前台首页只剩一行 There has been a critical error on this website。这类事故在商业主题大版本升级(比如从 1.x 到 2.x)时特别常见:目录结构被重写、老钩子被改名、子主题覆盖的模板文件失效,而你手里没有任何一份能回滚的备份。

真正稳妥的做法,是在点更新之前花十分钟做完三件事:确定能回滚、确定你的改动不在父主题里、确定这次更新动了什么。这三件事的顺序不能颠倒。

原理分析:主题更新到底覆盖了什么

WordPress 的主题更新走的是 Theme_Upgrader,流程是:下载 zip 包 → 解压 → 整个删除 wp-content/themes/{主题目录}/ → 把新包写进去。注意是”整个目录替换”,不是”增量补丁”。这意味着:

位置 更新后是否保留
wp-content/themes/父主题/ 内所有文件 全部被新包替换,自定义改动丢失
wp-content/themes/子主题/ 内文件 完全不受影响
主题的 theme_mods_XXX 设置(自定义器里的配置) 存在数据库,保留
数据库里的内容、文章、菜单 保留
wp-content/uploads/ 上传文件 保留

所以风险的唯一来源是”你把改动写进了父主题目录”。第二层风险是版本兼容:新主题可能要求更高的 PHP 版本或 WordPress 版本,也可能废弃了你在子主题里调用的函数,导致 Fatal error: Uncaught Error: Call to undefined function。

保姆级实操

第 1 步:做一份能真正回滚的备份

只备份数据库是不够的。主题更新需要”文件 + 数据库”两份,缺一不可。

# 进入站点根目录后执行(WP-CLI)
wp db export backup-$(date +%Y%m%d-%H%M).sql

# 只打包主题目录与上传目录,速度快、体积小
tar -czf themes-$(date +%Y%m%d).tar.gz wp-content/themes
tar -czf uploads-$(date +%Y%m%d).tar.gz wp-content/uploads

没有命令行的环境,可用 UpdraftPlus 或 BackWPup 做一次「文件 + 数据库」完整备份,确认备份文件已经落到远程存储(Google Drive / S3),而不是只躺在服务器本地磁盘上——服务器整盘故障时,本地备份等于没有。

第 2 步:确认改动是否在子主题里

后台「外观 → 主题文件编辑器」一旦被用过,八成改的是父主题。用下面这段一次性检查当前主题是不是子主题、父主题目录里有没有被改过的痕迹:

// 放到子主题 functions.php 或临时插件里,刷新后台任意页面查看
add_action( 'admin_notices', function () {
    $theme = wp_get_theme();
    $info  = array(
        '当前主题'   => $theme->get( 'Name' ) . ' ' . $theme->get( 'Version' ),
        '是否子主题' => $theme->parent() ? '是' : '否(改动会被更新覆盖!)',
        '父主题'     => $theme->parent() ? $theme->parent()->get( 'Name' ) . ' ' . $theme->parent()->get( 'Version' ) : '-',
    );
    echo '<div class="notice notice-info"><pre>' . esc_html( print_r( $info, true ) ) . '</pre></div>';
} );

如果确认改过父主题,先把改动搬走:模板类的覆盖复制到子主题同名路径,功能类的代码改用 remove_action / remove_filter 在子主题里解绑后再重写,具体操作可参考子主题覆盖父主题模板的正确姿势。

第 3 步:读懂变更日志再决定要不要升

商业主题的更新包里通常带 changelog.txt,WordPress.org 上的主题则在 readme.txt 的 == Changelog == 段。重点看三类字眼:Breaking Change / Deprecated / Bumped minimum PHP version。

# 本地解开更新包,只读变更日志,不急着装
unzip -p theme-v2.0.0.zip '*/changelog.txt' | head -n 60

看到”最低 PHP 要求提高到 8.0″而你的主机还在 7.4,就先升级 PHP 再动主题;看到”重构了模板目录结构”,就先去预发布环境验证子主题的覆盖文件还认不认。

第 4 步:先在预发布环境跑一遍

用子域或子目录搭一个克隆站,把生产站的数据库和文件导过去,在预发布环境里完成更新,然后逐项检查:首页、文章页、归档页、搜索页、移动端、WooCommerce 商品页(如有)、浏览器控制台有无 404 与 JS 报错。WP Staging 插件可以一键克隆到生产站同服务器,适合没有命令行权限的共享主机用户。

第 5 步:更新后立即体检

wp theme list          # 确认版本号与更新状态
wp option get stylesheet  # 确认当前启用主题没被切换
wp core verify-checksums  # 顺手确认核心文件没被动过

前台按 Ctrl + F5 强刷,因为旧的 CSS/JS 有浏览器缓存和页面缓存插件缓存,更新后样式错乱往往只是缓存没刷,可对照主题版本号与子主题版本号的关系处理缓存穿透。

常见踩坑

  1. 只备份数据库。 主题文件被替换后,数据库备份救不回模板,只能重装旧版本重新配置。
  2. 在父主题 functions.php 里加了自定义函数。 更新后函数消失,前台直接致命错误。所有自定义逻辑必须进子主题或功能插件。
  3. 子主题覆盖的文件”还在但失效了”。 父主题把 template-parts/header/logo.php 重命名为 branding.php 后,子主题里的老文件不会被调用,也不会被删除,表现为局部空白且无任何报错。
  4. 预发布环境与生产环境 PHP 版本不同。 预发布 PHP 8.2 正常,生产 PHP 7.4 白屏,测试结论失真。
  5. 更新后没清缓存。 开着 WP Rocket / LiteSpeed Cache 时,前台样式”错乱”其实是缓存未刷新,先清对象缓存与页面缓存再排查。
  6. 案例: 某外贸站给商业主题加了自定义 functions.php 代码和两处模板覆盖,运维直接点生产环境更新。父主题 2.0 把 inc/ 下多个文件合并,子主题 functions.php 顶部 require_once get_template_directory() . '/inc/helpers.php' 指向的文件已不存在,触发 Failed opening required,全站 500。最后靠主机商的每日快照回滚,中间停摆三小时。教训是:预发布验证 + 更新前快照,两样都不能省。
  7. 自动更新在半夜悄悄执行。 主题级自动更新可用 auto_update_theme 过滤器关掉,商业主题建议一律手动更新:
// 放在子主题 functions.php 或功能插件中,禁止主题自动更新
add_filter( 'auto_update_theme', '__return_false' );

总结

更新主题前的判断标准只有三条:能不能在十分钟内完整回滚、你的改动是不是全都在子主题或插件里、你知不知道这次更新改了什么。三条都满足才点更新;任何一条不满足,先补齐再动。落地顺序固定为:备份 → 子主题检查 → 读 changelog → 预发布验证 → 生产更新 → 清空各级缓存 → 前台逐页体检。把这套流程写成站点的运维清单,比记住任何一个”救命命令”都管用。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。