WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

What is the difference between $GLOBALS['wp_the_query'] and global $wp_query?

Why prefer one over the other?

share|improve this question
2  
I would say global $wp_query just to answer your question in one line! – Sumit Mar 14 at 8:17
    
What is the difference? – Nathan Powell Mar 14 at 8:23
up vote 14 down vote accepted

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

share|improve this answer
1  
query_posts() changes global $wp_query. global $wp_the_query holds the reference to the main query – Evan Mattson Mar 15 at 19:06
    
My comment wasn't intended as a correction, so my apologies if it did. I was merely summarizing (TL;DR if you will) while pointing out what I believe is one of the most significant aspects of $wp_the_query as it pertains to the WP_Query::is_main_query() method, which was not mentioned :D – Evan Mattson Mar 16 at 0:37
    
@EvanMattson Apologies, I misunderstood your first comment ;-). Yes, is_main_query(), which is a wrapper for WP_Query::is_main_query() which checks the current query object against the main query object saved in $GLOBALS['wp_the_query']. This is quite important when you run pre_get_posts actions and just want to target the main query ;-) – Pieter Goosen Mar 16 at 4:18
    
Pretty well done answer! @EvanMattson That should have been an edit. – kaiser Apr 6 at 21:49
    
@kaiser Thank you, appreciated ;-) – Pieter Goosen Apr 7 at 6:39

Basically one is copy of the other. Check out wp-settings.php, lines 292-305:

$GLOBALS['wp_the_query'] = new WP_Query();

$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
share|improve this answer

The global keyword imports the variable into the local scope, while $GLOBALS just grants you access to the variable.

To elaborate, if you use global $wp_the_query; you can use $wp_the_query inside the local scope without using the word global again. So basically global $wp_the_query can be compared to $wp_the_query = $GLOBALS['wp_the_query']

EDIT

I misread wp_query for wp_the_query so my answer isn't a complete answer to the question but still provides general information about the difference between global $variable and $GLOBALS['variable']

share|improve this answer
    
Please, file an edit as this really is not an answer to the original question. Just FYI $GLOBALS['foo'] allows overriding or unsetting the variable as well. So it's a bit more than what you describe here. – kaiser Apr 6 at 21:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.