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本身,和计数器

参考资料

相关推荐
两个人的幸福14 小时前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo3 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack3 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户3074596982074 天前
PHP 扩展——从入门到理解
php
鹏仔先生4 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下4 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
xingpanvip4 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
酉鬼女又兒5 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
dog2505 天前
不要再继续优化 TCP
网络协议·tcp/ip·php
Channing Lewis5 天前
PHP 解析 Excel 的那些坑:一次“行号错位”引发的数据丢失
开发语言·php·excel