What is the difference between $GLOBALS['wp_the_query']
and global $wp_query
?
Why prefer one over the other?
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.
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
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
global $wp_query
. global $wp_the_query
holds the reference to the main query
Commented
Mar 15, 2016 at 19:06
$wp_the_query
as it pertains to the WP_Query::is_main_query()
method, which was not mentioned :D
Commented
Mar 16, 2016 at 0:37
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 ;-)
Commented
Mar 16, 2016 at 4:18
is_main_query
function in the *IMPORTANT EDIT section? I was using pre_get_posts
today and found it utterly useful to use that function since I was looking at $wp_query
.
Commented
Mar 18, 2017 at 0:50
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']
global $wp_query
just to answer your question in one line!