An update to a talk I gave at WordCamp Portland 2011, "You Don't Know Query" is an advanced development talk from March 25, 2012, in Utrecht, Netherlands.
14. With the regular loop
while ( have_posts( ) ) :
the_post( );
if ( is_author( ) )
echo "An author query.";
endwhile;
15. With the regular loop
while ( have_posts( ) ) :
the_post( );
if ( $wp_query->is_author( ) )
echo "An author query.";
endwhile;
16. A secondary loop
$query = new WP_Query( … );
while ( $query->have_posts( ) ) :
$query->the_post( );
if ( $query->is_author( ) )
echo "An author query.";
endwhile;
17. A secondary loop
$query = new WP_Query( … );
while ( $query->have_posts( ) ) :
$query->the_post( );
if ( $query->is_author( ) )
echo "An author query.";
endwhile;
18. A secondary loop
$query = new WP_Query( … );
while ( $query->have_posts( ) ) :
$query->the_post( );
if ( $query->is_author( ) )
echo "An author query.";
endwhile;
19. If you do:
$my_query = new WP_Query( $query );
You can do:
while ( $my_query->have_posts( ) ) :
$my_query->the_post( );
endwhile;
wp_reset_postdata( );
20. Why do we call functions like
wp_reset_postdata( ) and
wp_reset_query( )?
What about using query_posts( )?
How can you alter a query? How
can you alter the main query?
21. What is the main query,
and why should I care?
22. wp-blog-header.php
// Load the WordPress bootstrap
require './wp-load.php';
// Do magic
wp( );
// Decide which template files to load
require WPINC . '/template-loader.php';
23. Let's look in the bootstrap:
$wp_the_query = new WP_Query();
$wp_query =& $wp_the_query;
33. WP::parse_request( )
— Parses the URL using WP_Rewrite
— Sets up query variables for WP_Query
WP::query_posts( ) {
global $wp_the_query;
$wp_the_query->query( $this->query_vars );
}
34. Boom.
SELECT SQL_CALC_FOUND_ROWS
wp_posts.*
FROM wp_posts
WHERE 1=1
AND wp_posts.post_type = 'post'
AND wp_posts.post_status = 'publish'
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10
40. 1. Get me my posts:
SELECT
SQL_CALC_FOUND_ROWS …
FROM wp_posts LIMIT 0, 10
2. How many posts exist?
SELECT FOUND_ROWS( )
3. Get all metadata for these posts.
4. Get all terms for these posts.
41. (You can turn these off selectively…)
$my_query = new WP_Query( array(
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
) );
52. 'pre_get_posts' fires for every post
query:
— get_posts( )
— new WP_Query( )
— That random recent posts widget your client
installed without you knowing.
— Everything.
55. Main query only!
function nacin_alter_home( $query ) {
global $wp_the_query;
if ( $wp_the_query === $query
&& $query->is_home() )
$query->set( 'author', '-5' );
}
add_action( 'pre_get_posts', 'nacin_alter_home' );
56. Hmm. How does this work?
$wp_the_query should never be modified. It
holds the main query, forever.
$wp_query keeps a live reference to
$wp_the_query, unless you use
query_posts( ).
61. function wp_reset_query( ) {
// Restore reference to $wp_the_query
unset( $wp_query );
$wp_query =& $wp_the_query;
// Reset the globals, too.
wp_reset_postdata( );
}
62. Calling the_post( )?
wp_reset_query( ) will reset $wp_query
and the globals.
Calling $my_query->the_post( )?
wp_reset_postdata( ) will reset the globals.
63. New in WordPress 3.3!
Rather than:
$wp_the_query === $other_query_object
You can call:
$other_query_object->is_main_query( )
is_main_query( ), the function, will act on
$wp_query, like any other conditional tag.
67. Some Lessons
Every WP_Query object has methods that
mimic the global conditional tags.
The global conditional tags apply to
$wp_query, the main or current query.
$wp_query is always the main query, unless
you use query_posts( ). Restore it with
wp_reset_query( ).
68. And Finally
pre_get_posts is a powerful and flexible hook.
Just use it properly.
Always check if you're modifying the main
query using $query->is_main_query( )