本文约 5,664 字,预计阅读 15 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:访客撞上死链,你的页面只给了他一句「找不到」
站点改版、文章删除、URL 规则变更、外链拼错——这些都会产生 404。默认主题的 404 页面通常只有一行「抱歉,找不到你要的页面」,最多再加一句「试试搜索」。访客此时只有一个选择:关掉标签页。而你为了把他引到这个页面付出的一切(外链建设、社交传播、广告投放)全部白费。
一个合格的 404 页面应该完成三件事:告诉用户发生了什么(这个地址不存在,不是你的错)、给他继续往下走的路(搜索框、热门内容、分类入口、返回首页)、顺便帮你发现问题(记录 404 URL,便于后续做 301)。技术上还有一条硬要求:404 页面必须真正返回 HTTP 404 状态码,而不是 200——否则搜索引擎会把它当成正常页面收录,产生大量「软 404」。
原理分析:模板优先级与状态码是两个独立问题
| 环节 | 负责者 | 关键点 |
|---|---|---|
| 模板选择 | 404.php → index.php |
只要有 404.php 就优先用它 |
| 状态码 | wp_redirect_admin_locations / handle_404() |
由 WP 主查询决定,模板改不了 |
| 争夺模板 | template_include 过滤器 |
可用于特殊场景接管 |
WordPress 在 WP::handle_404() 里判断当前请求是否为 404,并调用 status_header( 404 )。这里有个常见误解:如果你在 404.php 里用 query_posts() 或 new WP_Query() 输出内容,状态码不会改变,仍然是 404,这点不用担心。真正会把状态码变成 200 的是两种情况:服务器层面把 404 重写成了别的可访问页面;或者用了某些「智能重定向」插件把未知 URL 全部 302 到首页,这会产生大量软 404。
pre_handle_404 过滤器(在 handle_404() 开头触发)允许你提前干预:返回 true 表示「我已处理」,WordPress 不再做后续判断。这个钩子适合做自定义路由,普通 404 页面不需要动它。
内容层面,get_search_form() 会输出主题的 searchform.php,如果主题没有这个文件则输出内置表单。热门文章可以用 WP_Query 按 comment_count 或自定义浏览量字段排序。要注意 404 页面上的查询不要太重——它可能被爬虫大量访问。
保姆级实操
- 建 404.php:放在主题根目录,优先级高于
index.php。 - 确认状态码:用
curl -I检查返回的是 404 而不是 200。 - 放搜索框:
get_search_form()一行搞定,样式用主题现有搜索样式。 - 加热门内容:
WP_Query取评论数最多的 5–8 篇,或取指定分类的最新文章。 - 加分类与标签入口:
wp_list_categories()或wp_tag_cloud(),给访客更多选择。 - 记录 404 URL:写一个轻量的日志,便于后续批量做 301。
- 服务器配置:确保 nginx/Apache 把 404 交给 WordPress 处理,而不是返回服务器的默认错误页。
<?php
/**
* 404.php
*
* @package lumen-mimangfei-child
*/
get_header();
?>
<main id="primary" class="site-main site-main--404">
<section class="not-found">
<h1 class="not-found__code">404</h1>
<p class="not-found__desc">
这个地址已经不存在了,可能是链接过期或拼写有误。试试下面的搜索,或看看这些内容。
</p>
<div class="not-found__search">
<?php get_search_form(); ?>
</div>
</section>
<section class="not-found__popular" aria-labelledby="not-found-popular">
<h2 id="not-found-popular">热门文章</h2>
<?php
$q = new WP_Query( array(
'posts_per_page' => 6,
'ignore_sticky_posts' => true,
'orderby' => 'comment_count',
'order' => 'DESC',
'no_found_rows' => true,
) );
if ( $q->have_posts() ) :
?>
<ul class="not-found__list">
<?php
while ( $q->have_posts() ) :
$q->the_post();
?>
<li>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
<span class="not-found__meta">
<?php echo esc_html( get_the_date() ); ?>
</span>
</li>
<?php
endwhile;
wp_reset_postdata();
?>
</ul>
<?php
endif;
?>
</section>
<section class="not-found__cats" aria-labelledby="not-found-cats">
<h2 id="not-found-cats">按分类浏览</h2>
<ul>
<?php
wp_list_categories( array(
'title_li' => '',
'orderby' => 'count',
'order' => 'DESC',
'number' => 10,
'show_count' => true,
'hide_empty' => true,
) );
?>
</ul>
</section>
</main>
<?php
get_footer();
<?php
// 子主题 functions.php:轻量记录 404 URL,便于后续补 301
add_action( 'wp', 'mimangfei_log_404' );
function mimangfei_log_404() {
if ( ! is_404() ) {
return;
}
$path = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ) );
$transient = 'mmf_404_log';
$log = get_transient( $transient );
if ( ! is_array( $log ) ) {
$log = array();
}
if ( isset( $log[ $path ] ) ) {
$log[ $path ]++;
} elseif ( count( $log ) < 200 ) {
$log[ $path ] = 1;
}
set_transient( $transient, $log, WEEK_IN_SECONDS );
}
# nginx:把 404 交给 WordPress 处理,不要返回服务器默认页
error_page 404 /index.php?error=404;
location / {
try_files $uri $uri/ /index.php?$args;
}
# 验证 404 页面返回的状态码,必须是 404 而不是 200
curl -I https://example.com/this-page-does-not-exist
常见踩坑
- 返回 200 状态码:装了「404 重定向到首页」的插件,或用
wp_redirect()把 404 转走,搜索引擎会收录大量软 404。正确做法是保留 404 状态码,只在页面内容上给出出路。 - 服务器配置抢先:nginx 配了
error_page 404 /404.html,WordPress 的404.php根本不会被用到。静态错误页无法使用主题函数,必须把 404 交给 PHP。 - 案例:某站在 Search Console 里出现两千多条「已编入索引,但已提交 noindex」与「软 404」警告。排查发现他们为了让 404 页好看,用插件把所有未知 URL 302 到了首页——搜索引擎把首页当成了这些 URL 的内容,判定为软 404。改成返回真正的 404 状态码并保留好看的 404.php 后,警告在两个月内逐步清空。教训:重定向到首页是最糟糕的 404 处理方式。
- 404 页放了重量级查询:按浏览量排序 + 多篇全文,爬虫大量访问时数据库压力陡增。用
no_found_rows => true、限制条数,并加对象缓存。 - 搜索框指向了错误的 action:主题自建的搜索表单把
action写成了具体 URL,切换域名后失效。get_search_form()输出的表单用home_url( '/' ),更安全。 - 404 页放在了
noindex:404 页本身不会被索引(状态码决定),不要给它加 noindex,也不要在 robots.txt 里屏蔽。 - 改版后旧 URL 没做 301:404 页做得再好,也不如把旧地址正确重定向到新地址。定期看记录的 404 列表,把高频的做 301。
- 移动端样式没适配:404 页常被忽略响应式测试,两个按钮在窄屏下叠在一起。按
主题响应式断点设置建议的断点做一次窄屏检查。
总结
一个合格 404 页的判断标准是:状态码正确(404)+ 页面上有至少两条继续浏览的路径 + 高频 404 被记录下来并逐步做 301。行动清单:新建 404.php → 用 curl -I 确认状态码 → 加 get_search_form() 搜索框 → 加 6 条左右热门文章与分类入口 → 轻量记录 404 路径 → 检查 nginx/Apache 的 error_page 配置 → 每月看一次 404 记录补重定向。做完这步,可以接着优化 主题搜索结果页体验优化,让站内发现内容的第二条通路同样好用。
