$ GLOBALS ['wp_the_query']与全局$ wp_query


Answers:


27

您错过了一个$GLOBALS['wp_query']。出于所有目的,$GLOBALS['wp_query'] === $wp_query$GLOBALS['wp_query']然而,它具有更好的可读性,因此应代替$wp_query个人使用,但仍然是个人喜好

现在,在一个完美的世界里,独角兽统治世界,$GLOBALS['wp_the_query'] === $GLOBALS['wp_query'] === $wp_query。默认情况下,这应该是正确的。如果我们查看这些全局变量的设置位置(wp-settings.php),您会看到主查询对象存储在其中$GLOBALS['wp_the_query']$GLOBALS['wp_query']并且只是该对象的重复副本$GLOBALS['wp_the_query']

/**
 * WordPress Query object
 * @global WP_Query $wp_the_query
 * @since 2.0.0
 */
$GLOBALS['wp_the_query'] = new WP_Query();
/**
 * Holds the reference to @see $wp_the_query
 * Use this global for WordPress queries
 * @global WP_Query $wp_query
 * @since 1.5.0
 */
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];

这样做的原因是因为WordPress看到了query_posts1.5版的到来。

function query_posts($query) {
    $GLOBALS['wp_query'] = new WP_Query();
    return $GLOBALS['wp_query']->query($query);
}

如您所见,query_posts将主查询对象设置为当前的自定义查询开始运行。这破坏了主查询对象的完整性,从而为您提供了不正确的数据,因此依赖主查询对象的所有内容都会由于数据错误而损坏。

解决此问题的一种方法是创建另一个全局存储主查询对象,$GLOBALS['wp_the_query']该对象在2.0.0版中引入。这个新的全局保存主要查询对象,$GLOBALS['wp_query']只是一个副本。通过wp_reset_query(),我们现在可以重置$GLOBALS['wp_query']回原始的主查询对象,以恢复其完整性。

但这不是一个完美的世界,query_posts而是魔鬼本人。尽管有成千上万的警告,人们仍在使用query_posts。除了中断主查询之外,它还会重新运行主查询,从而使其与的常规自定义查询相比要慢得多WP_Query。许多人也不会在完成时重置query_posts查询wp_reset_query(),这会使query_posts情况更加恶劣。

因为我们无法执行任何操作,也无法停止使用插件和主题,query_posts并且我们永远无法知道是否使用query_posts重置了查询wp_reset_query(),所以我们需要主查询对象的更可靠副本,我们知道它将为我们提供99.99999%的可靠,正确数据。那是$GLOBALS['wp_the_query']有用的,因为没有WordPress相关代码可以更改其值(通过WP_Query自身内部的过滤器和操作除外)。

快速证明,运行以下命令

var_dump( $GLOBALS['wp_the_query'] );
var_dump( $GLOBALS['wp_query'] );

query_posts( 's=crap' );


var_dump( $GLOBALS['wp_the_query'] );
var_dump( $GLOBALS['wp_query'] );

并检查结果。$GLOBALS['wp_the_query']没有改变,并$GLOBALS['wp_query']有。那么哪个更可靠?

最后一点,$GLOBALS['wp_the_query']不是进行更换wp_reset_query()wp_reset_query()始终与使用query_posts,并且query_posts应该永远不会被使用。

结论

如果您需要几乎永远不会失败的可靠代码,请使用$GLOBALS['wp_the_query'];如果您信任并相信插件和主题代码,并且认为没有人query_posts正确使用$GLOBALS['wp_query']或正确使用它,请使用或$wp_query

重要编辑

现在在这个网站上回答问题已有两年了,我看到许多用户将其$wp_query用作局部变量,这反过来又破坏了主查询对象。这进一步增加了漏洞的脆弱性$wp_query

例如,有人对此

$wp_query = new WP_Query( $args );

从本质上讲,这与query_posts正在执行的操作完全相同


1
query_posts()更改global $wp_queryglobal $wp_the_query拥有对主要查询
Evan Mattson

我的评论并非旨在纠正,因此我对此表示歉意。我只是在概述(如果您愿意的话,可以是TL; DR),同时指出我认为是该方法最重要的方面之一$wp_the_query,但WP_Query::is_main_query()并未提及:D
Evan Mattson

@EvanMattson抱歉,我误解了您的第一条评论;-​​)。是的,is_main_query()这是一个包装器,WP_Query::is_main_query()它针对中保存的主查询对象检查当前查询对象$GLOBALS['wp_the_query']。当您运行pre_get_posts操作并且只想定位主要查询时,这非常重要;-)
Pieter Goosen

做得不错!@EvanMattson应该是编辑了
kaiser

您可以is_main_query在“重要编辑”部分中提及功能吗?我pre_get_posts今天使用的是该功能,因为我一直在看,所以使用它完全有用$wp_query
内森·鲍威尔


2

global关键字将变量导入本地范围,而$ GLOBALS仅授予您访问变量的权限。

详细地说,如果使用global $wp_the_query; ,可以$wp_the_query在本地范围内使用,而无需再次使用global。所以基本上global $wp_the_query可以比较$wp_the_query = $GLOBALS['wp_the_query']

编辑

我看错wp_query为wp_the_query所以我的答案是不完整的问题的答案,但仍然提供了有关之间的差异的一般信息global $variable$GLOBALS['variable']


请进行编辑,因为这实际上不是原始问题的答案。仅供参考,也$GLOBALS['foo']可以覆盖或取消设置变量。所以这是一个有点超过你的描述在这里。
kaiser 2016年
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.