12. 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( );
13. But why do we call things like
wp_reset_postdata( ) and
wp_reset_query( )?
What about using query_posts( )?
How can you alter a query? What
about the main query?
14. What is the main query,
and why should I care?
27. 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 );
}
28. 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
29. wp-blog-header.php
// Load WordPress.
require dirname(__FILE__) . '/wp-load.php';
// Parse what to query, and query it.
wp();
// Load the theme.
ABSPATH . WPINC . '/template-loader.php';
30. Before we get to the theme,
we have your posts.
Got it?
31. Then why do we do this?
query_posts( 'author=5' );
get_header( );
while( have_posts( ) ) :
the_post( );
endwhile;
get_footer( );
32. That's running 2* queries!
One, the query WordPress
thought we wanted.
Two, this new one you're
actually going to use.
34. 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. Slurp all metadata for these posts.
4. Slurp all terms for these posts.
36. (A note, 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,
) );
42. Powerful, but lacks context.
Problem 1: Conditional tags don't work yet.
Problem 2: Only works on the main query.
43. Powerful, but lacks context.
Problem 1: Conditional tags don't work yet.
Problem 2: Only works on the main query.
Problem 3: WP_Query is waaay cooler.
44. Introducing pre_get_posts
class WP_Query {
. . .
function &get_posts() {
$this->parse_query();
// Huzzah! Conditional tags are available.
do_action_ref_array( 'pre_get_posts',
array( &$this ) );
. . .
45. A truly awesome hook.
function nacin_alter_home( $query ) {
if ( $query->is_home( ) )
$query->set( 'author', '-5' );
}
add_action( 'pre_get_posts', 'nacin_alter_home' );
47. 'request' fires for the main query only.
'pre_get_posts' fires for every post query:
— get_posts()
— new WP_Query()
— That random recent posts widget.
— Everything.
50. Main query only!
function nacin_alter_home ( $query ) {
if ( $wp_the_query === $query
&& $query->is_home() )
$query->set( 'author', '-5' );
}
add_action( 'pre_get_posts', 'nacin_alter_home' );
51. 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().
56. class WP_Query {
. . .
function wp_reset_query( ) {
// Restore the reference to
$wp_the_query
unset( $wp_query );
$wp_query =& $wp_the_query;
// Reset the globals, too.
wp_reset_postdata( );
. . .
57. Calling the_post( )?
wp_reset_query( ) will reset $wp_query
and and the globals.
Calling $my_query->the_post( )?
wp_reset_postdata( ) will reset the globals.
58. New thing for core in 3.3!
Rather than:
$wp_the_query === $other_query_object
You'll be able to call:
$other_query_object->is_main_query( )
is_main_query( ), the function, will act on
$wp_query, like any other conditional tag.
59. 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( ).
60. And Finally
request is a nice hook. pre_get_posts is more
powerful and flexible. Just use it properly.
Always check if you're modifying the main query
using $query === $wp_the_query
$query->is_main_query( ) in 3.3!