问题描述
我遇到了一个奇怪的问题。
说你访问一个随机 url,三个或更多的层次:
http://example.com/a/b/c
http://example.com/a/b/c/d
...
那么 is_404()
是 true
。到现在为止还挺好。但是由于某些原因,最后的帖子被查询。
$wp_query->request
是
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (
wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private'
)
ORDER BY wp_posts.post_date DESC
LIMIT 0, 5
那当然这使得 have_posts()
返回 true
等等。有人可以解释一下吗
我发现到目前为止
只有三点或更多级别深入的原因是,在 WP 查找帖子和附件之前,这些结果会导致其他一些行为。
似乎即使 WP 在一点上将该请求识别为 404,然后获取最新的帖子。在 @kaiser 和 @G.M. 的帮助下,我已经将其跟踪到了/wp-includes/class-wp.php:608 的某个地方
最佳解决方案
你可能会惊讶,但没有什么奇怪的。
首先让我们澄清一下,在 WordPress 中,当您访问前端 URL 时,您将触发查询。总是。
该查询只是一个标准的 WP_Query
,就像通过以下方式运行的那样:
$query = new WP_Query( $args );
只有一个区别:$args
变量由 WordPress 使用 WP::parse_request()
方法生成。该方法的作用是查看 URL,并重写规则,并将 URL 转换为参数数组。
但是,由于 URL 是 non-valid,那个方法不能做到这一点呢?查询 args 只是一个这样的数组:
array( 'error' => '404' );
所以将该数组传递给 WP_Query
。
现在尝试做:
$query = new WP_Query( array( 'error' => '404' ) );
var_dump( $query->request );
您是否惊讶于查询完全是 OP 中的查询?我不是。
所以,
-
parse_request()
构建一个带有错误键的数组 -
该数组被传递给
WP_Query
,它只是运行它 -
在查询后运行的
handle_404()
,查看'error'
参数,并将is_404()
设置为 true
所以 have_post()
和 is_404()
是无关的。问题是 WP_Query
在出现错误时没有向 short-circuit 询问系统,所以一旦对象被建立,传递一些参数就可以运行查询。
编辑:
有两种方法来克服这个问题:
-
创建
404.php
模板; WordPress 将加载 404 网址,您不需要检查have_posts()
-
强制
$wp_query
在 404 上为空,类似于:add_action( 'wp', function() { global $wp_query; if ( $wp_query->is_404() ) { $wp_query->init(); $wp_query->is_404 = true; // init() reset 404 too } } );
参考文献
注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。