为什么在某些404上循环不为空?


10

我遇到了一个奇怪的问题。

假设您访问一个随机网址,深度为三个或三个以上级别:

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@GM的帮助下,我已将此问题跟踪到/wp-includes/class-wp.php:608的某个位置。


如果不添加该页面的代码会是很难帮助你
托马斯科特

3
这不是我的代码专用的。在具有所有默认主题的全新安装上,其行为也是如此。
kraftner 2014年

您能否命名至少一个主题,因为我的自定义主题无效?您是否在使用特定参数?你换了吗?您正在使用哪个版本的WP?
托马斯科特

真的可以 但是,如果您愿意,请尝试二十一。
kraftner 2014年

对不起所有问题,我以为帖子正在显示。
托马斯科特

Answers:


9

您可能会感到惊讶,但是没有什么奇怪的。

首先,让我们澄清一下,在WordPress中,当您访问前端URL时会触发查询。总是。

该查询只是一个标准WP_Query,就像通过以下方式运行的查询一样:

$query = new WP_Query( $args );

仅有一个区别:$args变量是由WordPress使用该WP::parse_request()方法生成的。该方法所做的只是查看URL和重写规则,然后将URL转换为参数数组。

但是,当该方法由于URL无效而无法执行此操作时会发生什么?查询args只是这样的数组:

array( 'error' => '404' );

这里这里的来源)。

因此该数组将传递给WP_Query

现在尝试做:

$query = new WP_Query( array( 'error' => '404' ) );
var_dump( $query->request );

您对查询恰好是OP中的查询感到惊讶吗?我不是。

所以,

  1. parse_request() 用错误键构建一个数组
  2. 该数组传递给WP_Query,然后运行它
  3. handle_404()在查询运行,查看'error'参数并将其设置is_404()为true

所以,have_post()is_404()无关。问题是WP_Query没有系统会在出现问题时使查询短路,因此一旦构建了对象,请将一些args传递给它,查询将运行。

编辑:

有两种方法可以解决此问题:

  • 创建一个404.php模板;WordPress会将其加载到404 URL上,您无需检查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
        }
    } );

4
我要补充一点,通常不会发生这种情况的原因是404通常是query的结果。但是在这种情况下,这是重写规则$wp->matched_rule不匹配的结果,但是查询仍在进行中,因为它没有注意这一点。
Rarst 2014年

+1。是的,查询不关注它,而对于当前代码,它无法关注,因为无法停止它。例如,当查询无效分类法时WHERE 1=0,由于无法停止查询而在sql中设置了WordPress ,因此强制查询不返回任何内容... @Rarst
gmazzap

好吧,我明白了。因此,仍然存在的真正问题是,为什么在不返回任何合理参数的情况下,WP_Query假设默认查询获取帖子,而什么都不返回却更有意义?
kraftner 2014年

2
@kraftner表示WordPress无法避免查询运行,并且当没有合理的参数时,有2种选择:运行确定不返回任何内容的查询(例如查询无效分类法时,请参见上面的注释)或运行默认查询。为什么在这种情况下WP为什么选择后者是应该向核心开发人员提出的问题:)
gmazzap

@TomásCot当然可以,但是如果失败了,我希望它真正失败并且不返回完全不相关的内容。无论如何,现在事情已经解决了,我只需要再进行一次is_404()检查。
kraftner 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.