WordPress中手动返回404的优雅方式

这篇文章也可以在我的博客中查看

关于本文

WordPress虽然有比较完善的404处理机制,但有时候我们需要手动返回404,这篇文章就来探讨一下这个问题。

何时返回404

根据mdn,404用作示意客户端找不到相应的资源,这可能是:

  • 资源不存在
  • 资源不应该被访问
    • 与403相比:403指的是可被访问但强调用户"无权"

第一种情况WordPress会为我们处理,但第二种情况,往往需要我们手动驳回

Core是怎么做的?

先来看看WordPress Core是怎么做的,方便抄作业

class-wp.php中的handle_404()中可以看到以下逻辑:

随版本更新文件和函数内容可能有变,此是2023-8-12的内容

php 复制代码
handle_404()
{
	...
	$wp_query->set_404();
	status_header( 404 );
	nocache_headers();
	...
}
  1. 首先使用全局变量$wp_query设置404
  2. 然后设置响应头代码为404
  3. 最后设置响应头为:不添加缓存处理(no-cache-headers)
  • 它会将Cache-Control从响应头中移除

所以入乡随俗,我们也应该这么做

远古做法

在WordPress Hook还没成熟之前,习惯在WordPress处理完404之后的第一个钩子继续进行404处理

因此会选择在'wp'钩子手动返回404:

php 复制代码
add_action('wp', function () {
    if (/* contidtion */) {
        global $wp_query;
        $wp_query->set_404();
        status_header(404);
		nocache_headers();
    }
});

nocache_headers()是可选的,但core做了,我就跟着做了

新做法

后来WordPress给了一个pre_handle_404,在WordPress本身的handle_404()真正执行之前

这个filterhook需要返回一个单值:

  • false时继续执行handle_404()
  • 否则将短路handle_404()的执行

这给了我们一个手动处理404的机会

php 复制代码
add_filter('pre_handle_404', function ($_, $wp_query) {
    if (/* contidtion */) {
        //设置404
        $wp_query->set_404();
        status_header(404);
        nocache_headers();
    }
    return false;
}, 10, 2);

至于是否需要短路handle_404()的执行

就我们这个例子而言不需要

因为我们手动设置了404,而handle_404()会在已经是404的情况下自动短路

因此无论是return false还是return其它,handle_404()都不会执行

问题修复

阴差阳错之间让我发现一个小问题

如果在主查询有结果的情况下(have_posts() === true)返回404,整个主循环(main loop)还是有效的,但事实上我们返回错误时不希望主循环生效,因此我们可以考虑手动清空主循环:

php 复制代码
add_filter('pre_handle_404', function ($_, $wp_query) {
    if (/* contidtion */) {
        //清空文章
        $wp_query->posts = [];
        unset($wp_query->post);
        $wp_query->post_count = 0;
		
        //设置404
        $wp_query->set_404();
        status_header(404);
        nocache_headers();
    }
    return false;
}, 10, 2);

主要是清空了posts本身,和计数器

参考资料

相关推荐
绵山介子推4 小时前
IP地址、端口、TCP介绍、socket介绍、程序中socket管理
网络协议·tcp/ip·php·嵌入式软件
sadoshi5 小时前
phpstudy的Apache添加AddType application/x-httpd-php .php .php5配置无效的处理方式
开发语言·php·apache
八戒社12 小时前
WooCommerce短代码Shortcodes使用方法
前端·wordpress·woocommerce
s_little_monster12 小时前
【Linux】socket网络编程基础
linux·运维·网络·笔记·学习·php·学习方法
筱宇***1 天前
Mac的web服务器
mysql·nginx·macos·php
iangyu1 天前
【windows server脚本每天从网络盘复制到本地】
开发语言·windows·php
YUJIANYUE1 天前
PHP黑白胶卷底片图转彩图功能 V2025.05.15
php
为自己_带盐1 天前
浅聊一下数据库的索引优化
开发语言·数据库·php
Lucky小小吴2 天前
木马查杀篇—Opcode提取
php·opcode·木马查杀
邪恶的贝利亚2 天前
《ffplay 读线程与解码线程分析:从初始化到 seek 操作,对比视频与音频解码的差异》
ffmpeg·php·音视频