搜索全站
报错排查 8 分钟阅读

WordPress 报错 Cannot redeclare function?函数重复声明修复

网站突然白屏或提示"此站点遇到了致命错误"?日志里写着 Cannot redeclare function?本文讲清函数重复声明的成因,给出 function_exists 包裹、改用 require_once 等几种可直接照做的修复方法。

U
UFO_PF 2026-10-10 · 阅读 8 分钟
Wo 报错排查
阅读提示
本文约 3,005 字,预计阅读 8 分钟。文中命令与配置均经过实测,可直接参考执行。

引言

你改完 functions.php 保存,刷新网站——白屏了。前台只留下一行”此站点遇到了致命错误。”(英文是 There has been a critical error on this website.),后台同样打不开。去服务器看 wp-content/debug.log,看到长长的一行:”PHP Fatal error: Cannot redeclare xxx() (previously declared in /wp-content/themes/你的主题/functions.php:120) in /wp-content/themes/你的主题/functions.php on line 260″。这类报错在给网站加自定义代码、从网上抄一段 snippet 复制粘贴的时候特别高发。它和普通语法错误不同,语法没错、代码本身能跑,问题是同一个函数被定义了两遍,PHP 不允许,于是直接终止整个请求。好消息是它的原因非常单纯,定位和修复都不难,本文把成因和几种标准解法一次讲透。

故障原因分析

  1. 函数真的被写了两遍。 最常见的场景是把一段代码复制进 functions.php,结果同一段函数前后粘贴了两次,PHP 在加载时第二次遇到同名函数就报”无法重复声明”。
  1. 子主题和父主题定义了同名函数。 很多人把父主题 functions.php 里的一段函数原样复制到子主题去改,而父主题文件依然加载,父子两处都有同名函数,冲突就来了。
  1. 主题与插件撞名。 插件和主题各自定义了同名函数(尤其是名字很通用的 get_xxx()、custom_excerpt() 这类),谁后加载谁触发报错。
  1. 同一个文件被引入两次。 用 require 或 include 引入自定义文件时,如果引入动作执行了两遍,里面的函数会被定义两次。改用 require_once 就能避免。
  1. 代码片段类插件与主题里各写了一份。 用 Code Snippets 之类插件添加过一段函数,后来又在主题里加了同样一段,两处叠加导致重复。

分步解决方案

先定位两处声明。 报错信息是”金线索”,它明确告诉了你两个文件的路径和行号:

Cannot redeclare my_function() (previously declared in A.php:120) in B.php on line 260
  • A.php:120 是第一次声明的位置。
  • B.php:260 是第二次(触发报错)的位置。

只要删掉其中一处、或把其中一处改名,报错立刻消失。若你在前台看不到这句话,就去 wp-content/debug.log 里找,方法是在 wp-config.php 中开启日志:

// wp-config.php
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

方法一:删除或合并重复定义(最直接)

按上面定位到的两个文件,确认功能重复后,保留一份、删除另一份。如果是子主题复制父主题函数导致,删掉子主题里那份,改用下面方法三的”包裹”方式重写。

方法二:用 function_exists() 包裹(最通用)

无论函数出在哪个文件,都可以用 function_exists() 做存在性判断,保证同名函数只会被定义一次:

// functions.php(放在函数定义外层即可)
if ( ! function_exists( 'my_custom_excerpt' ) ) {
    function my_custom_excerpt( $length = 100 ) {
        // 你的函数逻辑
        return $length;
    }
}

这是 WordPress 生态里最推荐的写法,很多成熟主题和插件的自定义函数都用它兜底。它的好处是:谁先加载谁生效,后面遇到同名函数会安静地跳过,不会再白屏。

方法三:把 require 改成 require_once

如果报错来自”文件被引入两次”,检查你引入自定义文件的那一行:

// 错误写法:多处执行会重复加载
require get_template_directory() . '/inc/custom.php';

// 正确写法:只加载一次
require_once get_template_directory() . '/inc/custom.php';

方法四:给函数加命名前缀

如果同名函数分别来自两个不同的代码来源,又都舍不得改,可以给其中一个改名,加个独立前缀避免撞车:

// 修改前
function custom_breadcrumb() { /* ... */ }

// 修改后,加前缀降低撞名概率
function mimangfei_custom_breadcrumb() { /* ... */ }

改名前记得同步替换所有调用它的地方,否则会引发”函数未定义”的新错误。

方法五:把自定义代码放进插件

更规范的做法是把自定义函数放进一个自己写的小型插件(在 wp-content/plugins/ 下建目录和一个 PHP 文件,文件头写好插件注释),而不是塞进主题。插件在切换主题时依然生效,也更容易通过插件总开关一键停用,方便排查。

白屏后如何先恢复访问

如果连后台都进不去,可以用 FTP 把出问题的 functions.php 备份后,临时把新增的那段代码删掉或改回修改前的版本,让网站先恢复,再慢慢调试。不确定是哪段代码时,先停用所有主题相关自定义文件,或切回官方默认主题。

常见踩坑点

  1. 只看行号就动手改。 要同时看”first declared”和”on line”两处,只删一处往往不够,因为可能有三处重复。
  2. function_exists() 包错了位置。 它必须包在函数定义的最外层,包在函数体里面毫无作用。
  3. 改名后忘了改调用。 给函数加前缀后,所有引用它的地方都要一起改,否则会变成”Call to undefined function”。
  4. 在父主题里改函数。 直接在父主题 functions.php 里改,主题一更新就被覆盖;应该用子主题或自定义插件。
  5. 调试完好习惯没养成。 WP_DEBUG 长期开着会向前台暴露路径信息,排查完记得关闭或至少关闭显示。
  6. 忽视缓存。 有些主机开了 OPcache,改完 PHP 文件需要清一次或重启 PHP,否则可能还在跑旧代码,误以为没修好。

总结

Cannot redeclare function 这个报错名字很直白:同一个函数被声明了两次,PHP 就直接罢工。它的报错信息会精确给出两个文件路径和行号,这是最省事的线索——照着删掉或合并其中一处即可。日常写代码时,养成两个习惯就能规避绝大部分此类问题:自定义函数统一用 function_exists() 包裹,引入文件统一用 require_once。如果代码需要长期保留,建议做成自定义插件,既不受主题切换影响,也方便随时停用。把这几招用熟,再遇到 PHP 致命错误时你就不会手足无措,能几分钟内让网站恢复访问。

U
UFO_PF作者

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

留下你的想法

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