$GLOBALS[‘wp_the_query’] vs global $wp_query

You have missed one, $GLOBALS['wp_query']. For all purposes, $GLOBALS['wp_query'] === $wp_query. $GLOBALS['wp_query'] is however better for readability and should be used instead of $wp_query, BUT, that remains personal preference

Now, in a perfect world where unicorns rule the world, $GLOBALS['wp_the_query'] === $GLOBALS['wp_query'] === $wp_query. By default, this should be true. If we look at where these globals are set (wp-settings.php), you will see the main query object is stored in $GLOBALS['wp_the_query'] and $GLOBALS['wp_query'] is just a duplicate copy of $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'];

The reason for doing it this way, is because WordPress saw the arrival of query_posts in version 1.5.

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

As you can see, query_posts sets the main query object to the current custom query beign run. This breaks the integrity of the main query object, which gives you incorrect data, so anything that relies on the main query object is broken due to wrong data.

A way to counter this was to create another global to store the main query object, $GLOBALS['wp_the_query'] which was introduced in version 2.0.0. This new global hold the main query object and $GLOBALS['wp_query'] just a copy. Through wp_reset_query(), we could now reset $GLOBALS['wp_query'] back to the original main query object to restore its integrity.

But this is not a perfect world, and query_posts are the devil himself. Although thousands of warnings, people still use query_posts. Apart from breaking the main query, it reruns the main query, making it much slower as a normal custom query with WP_Query. Many people also do not reset the query_posts query with wp_reset_query() when done, which makes query_posts even more evil.

Because we cannot do anything about that, and cannot stop plugins and themes from using query_posts and we can never know if a query_posts query was reset with wp_reset_query(), we need a more reliable copy of the main query object which we know will give us 99.99999% reliable, correct data. That is where $GLOBALS['wp_the_query'] is useful as no WordPress related code can change it’s value (except through the filters and actions inside WP_Query itself).

Quick proof, run the following

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'] );

and check the results. $GLOBALS['wp_the_query'] did not change, and $GLOBALS['wp_query'] has. So which is more reliable?

Final note, $GLOBALS['wp_the_query'] is NOT a replacement for wp_reset_query(). wp_reset_query() should always be used with query_posts, and query_posts should never be used.

TO CONCLUDE

If you need reliable code which will almost always never fail, use $GLOBALS['wp_the_query'], if you trust and believe plugins and theme code and believe no one uses query_posts or is using it correctly, use $GLOBALS['wp_query'] or $wp_query

IMPORTANT EDIT

Being answering questions on this site now for a couple of years, I saw many users using $wp_query as a local variable, which in turn also breaks the main query object. This further increases the vulnerabilty of the $wp_query.

As example, some people to this

$wp_query = new WP_Query( $args );

which is in essence the exactly the same as what query_posts are doing

Leave a Comment