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

参考资料

相关推荐
码云数智-大飞6 小时前
PHP 接口开发规范:统一返回格式、异常处理与参数校验
开发语言·php
dadaobusi6 小时前
仿真边界处理
开发语言·php
微学AI9 小时前
内网穿透的应用-把飞牛NAS变成家庭录像中心:EasyNVR部署与远程回放实战
开发语言·php
峥嵘life9 小时前
Android WiFi连接过程 wpa_supplicant 日志分析
android·开发语言·php
weixin_BYSJ19879 小时前
「课设设计」springboot校园超市助购系统26449 (附源码)
java·javascript·spring boot·python·django·flask·php
xuefeiniao10 小时前
CentOS + 宝塔服务器偶发 SSH、面板、网站全部无法访问排查记录(PHP-FPM 内存耗尽案例)
服务器·centos·ssh·php
神州世通1 天前
解密企业通信安全防线:Avaya Aura 三层安全架构深度解析
开发语言·php
AC赳赳老秦1 天前
企业工商公开信息采集分析:OpenClaw 批量查询企业工商信息,生成企业画像报告
大数据·开发语言·python·自动化·php·deepseek·openclaw
AC赳赳老秦1 天前
司法公开数据采集应用:OpenClaw 抓取裁判文书公开信息,批量整理同类参考案例
java·大数据·python·数据挖掘·数据分析·php·openclaw
Vae_Mars1 天前
C#中多线程异步操作的方法-Parallel.ForEachAsync
开发语言·c#·php