Top Banner
WordCamp Netherlands 2012
69

You Don't Know Query (WordCamp Netherlands 2012)

May 17, 2015

Download

Technology

andrewnacin

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.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: You Don't Know Query (WordCamp Netherlands 2012)

WordCamp Netherlands 2012

Page 2: You Don't Know Query (WordCamp Netherlands 2012)

Andrew Nacin

Core Developer of WordPress and Tech Ninja at Audrey Capital

@nacin on Twitter [email protected]

Page 3: You Don't Know Query (WordCamp Netherlands 2012)

You Don’t Know Query

Page 4: You Don't Know Query (WordCamp Netherlands 2012)

What do you know?

Page 5: You Don't Know Query (WordCamp Netherlands 2012)

Conditional Tags

is_author( ), is_home( ), etc.

Page 6: You Don't Know Query (WordCamp Netherlands 2012)

query_posts( )

Page 7: You Don't Know Query (WordCamp Netherlands 2012)

Ways to query

query_posts( ) new WP_Query( ) get_posts( )

Page 8: You Don't Know Query (WordCamp Netherlands 2012)

The Loop

while ( have_posts( ) ) :

the_post( ); endwhile;

Page 9: You Don't Know Query (WordCamp Netherlands 2012)

A secondary loop

$query = new WP_Query( … ); while ( $query->have_posts( ) ) :

$query->the_post( ); endwhile;

Page 10: You Don't Know Query (WordCamp Netherlands 2012)

An array of posts

$result = get_posts( … ); foreach ( $result as $post_obj ) { }

Page 11: You Don't Know Query (WordCamp Netherlands 2012)

What don’t you know?

Page 12: You Don't Know Query (WordCamp Netherlands 2012)

Every query object has its own methods

is_author( ) is the same as calling $wp_query->is_author( )

Page 13: You Don't Know Query (WordCamp Netherlands 2012)

function is_author( ) {

global $wp_query;

return $wp_query->is_author( ); }

Page 14: You Don't Know Query (WordCamp Netherlands 2012)

With the regular loop

while ( have_posts( ) ) :

the_post( ); if ( is_author( ) ) echo "An author query.";

endwhile;

Page 15: You Don't Know Query (WordCamp Netherlands 2012)

With the regular loop

while ( have_posts( ) ) :

the_post( ); if ( $wp_query->is_author( ) ) echo "An author query.";

endwhile;

Page 16: You Don't Know Query (WordCamp Netherlands 2012)

A secondary loop

$query = new WP_Query( … ); while ( $query->have_posts( ) ) :

$query->the_post( ); if ( $query->is_author( ) ) echo "An author query.";

endwhile;

Page 17: You Don't Know Query (WordCamp Netherlands 2012)

A secondary loop

$query = new WP_Query( … ); while ( $query->have_posts( ) ) :

$query->the_post( ); if ( $query->is_author( ) ) echo "An author query.";

endwhile;

Page 18: You Don't Know Query (WordCamp Netherlands 2012)

A secondary loop

$query = new WP_Query( … ); while ( $query->have_posts( ) ) :

$query->the_post( ); if ( $query->is_author( ) ) echo "An author query.";

endwhile;

Page 19: You Don't Know Query (WordCamp Netherlands 2012)

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( );

Page 20: You Don't Know Query (WordCamp Netherlands 2012)

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?

Page 21: You Don't Know Query (WordCamp Netherlands 2012)

What is the main query, and why should I care?

Page 22: You Don't Know Query (WordCamp Netherlands 2012)

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

Page 23: You Don't Know Query (WordCamp Netherlands 2012)

Let's look in the bootstrap: $wp_the_query = new WP_Query(); $wp_query =& $wp_the_query;

Page 24: You Don't Know Query (WordCamp Netherlands 2012)

Quick lesson on PHP references

$a = 4; $b =& $a; $b = 2; var_dump( $a ); // int(2) $a = 6; var_dump( $b ); // int(6)

Page 25: You Don't Know Query (WordCamp Netherlands 2012)

So: So the real main query is in $wp_the_query. And a live copy of it is stored in $wp_query.

Page 26: You Don't Know Query (WordCamp Netherlands 2012)

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

Page 27: You Don't Know Query (WordCamp Netherlands 2012)

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

Page 28: You Don't Know Query (WordCamp Netherlands 2012)

What is that wp( ) call?

function wp( $query_vars = '' ) { global $wp;

$wp->main( $query_vars );

}

Page 29: You Don't Know Query (WordCamp Netherlands 2012)

Holy $!@?, what just happened?

Page 30: You Don't Know Query (WordCamp Netherlands 2012)

In the bootstrap:

$wp = new WP( ); So there's a wp( ) function, and a WP class.

Page 31: You Don't Know Query (WordCamp Netherlands 2012)

class WP { . . . function main( ) { $this->init( ); $this->parse_request( ); $this->send_headers( ); $this->query_posts( ); $this->handle_404( ); $this->register_globals( ); . . .

Page 32: You Don't Know Query (WordCamp Netherlands 2012)

class WP { . . . function main( ) { $this->init( ); $this->parse_request( ); $this->send_headers( ); $this->query_posts( ); $this->handle_404( ); $this->register_globals( ); . . .

Page 33: You Don't Know Query (WordCamp Netherlands 2012)

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

}

Page 34: You Don't Know Query (WordCamp Netherlands 2012)

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

Page 35: You Don't Know Query (WordCamp Netherlands 2012)

wp-blog-header.php // Load WordPress. require './wp-load.php'; // Parse what to query. Then query it. wp( ); // Load the theme. require WPINC . '/template-loader.php';

Page 36: You Don't Know Query (WordCamp Netherlands 2012)

Before we get to the theme, we have your posts.

Got it?

Page 37: You Don't Know Query (WordCamp Netherlands 2012)

Then why do we do this?

query_posts( 'author=-5' ); get_header( ); while( have_posts( ) ) : the_post( ); endwhile; get_footer( );

Page 38: You Don't Know Query (WordCamp Netherlands 2012)

That's running 2* queries! One, the query WordPress thought we wanted. Two, this new one you're actually going to use.

Page 39: You Don't Know Query (WordCamp Netherlands 2012)

* Actually, WP_Query doesn't run just one query. It usually runs four.

Page 40: You Don't Know Query (WordCamp Netherlands 2012)

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.

Page 41: You Don't Know Query (WordCamp Netherlands 2012)

(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,

) );

Page 42: You Don't Know Query (WordCamp Netherlands 2012)

</aside>

Page 43: You Don't Know Query (WordCamp Netherlands 2012)

PROTIP ‘Measure twice, cut once’ is bad for performance.

Page 44: You Don't Know Query (WordCamp Netherlands 2012)

Other problems with query_posts( )

Page 45: You Don't Know Query (WordCamp Netherlands 2012)

Pagination breaks. WordPress calculated paging using the query it did, not the query you did.

Page 46: You Don't Know Query (WordCamp Netherlands 2012)

query_posts( array( 'author' => -5, 'posts_per_page' => 25,

) ); This will not work well.

Page 47: You Don't Know Query (WordCamp Netherlands 2012)

You easily mess up globals.

This can break widgets and more.

Page 48: You Don't Know Query (WordCamp Netherlands 2012)

query_posts( ) is bad. Do we agree?

Page 49: You Don't Know Query (WordCamp Netherlands 2012)

Introducing pre_get_posts class WP_Query {

. . . function &get_posts() { $this->parse_query(); // Huzzah! do_action_ref_array( 'pre_get_posts', array( &$this ) ); . . .

Page 50: You Don't Know Query (WordCamp Netherlands 2012)

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

Page 51: You Don't Know Query (WordCamp Netherlands 2012)

Still with us?

Good, ‘cause here’s where things get complicated.

Page 52: You Don't Know Query (WordCamp Netherlands 2012)

'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.

Page 53: You Don't Know Query (WordCamp Netherlands 2012)

What if I just want it on the main query?

Page 54: You Don't Know Query (WordCamp Netherlands 2012)

$wp_the_query makes a triumphant return.

Page 55: You Don't Know Query (WordCamp Netherlands 2012)

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

Page 56: You Don't Know Query (WordCamp Netherlands 2012)

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( ).

Page 57: You Don't Know Query (WordCamp Netherlands 2012)

query_posts( 'author=-5' ); while ( have_posts( ) ) :

the_post( ); endwhile; wp_reset_query( );

Page 58: You Don't Know Query (WordCamp Netherlands 2012)

query_posts( 'author=-5' ); while ( have_posts( ) ) :

the_post( ); endwhile; wp_reset_query( );

Page 59: You Don't Know Query (WordCamp Netherlands 2012)

function query_posts( $query ) { // Break the reference to $wp_the_query unset( $wp_query ); $wp_query =& new WP_Query( $query ); return $wp_query;

}

Page 60: You Don't Know Query (WordCamp Netherlands 2012)

query_posts( 'author=-5' ); while ( have_posts( ) ) :

the_post( ); endwhile; wp_reset_query( );

Page 61: You Don't Know Query (WordCamp Netherlands 2012)

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( );

}

Page 62: You Don't Know Query (WordCamp Netherlands 2012)

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.

Page 63: You Don't Know Query (WordCamp Netherlands 2012)

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.

Page 64: You Don't Know Query (WordCamp Netherlands 2012)

What about page templates?

Page 65: You Don't Know Query (WordCamp Netherlands 2012)

/* Template: My Template */ query_posts( $query_string .

'&author=-5&posts_per_page=25' ); get_header( ); while ( have_posts( ) ) :

the_post( ); endwhile;

Page 66: You Don't Know Query (WordCamp Netherlands 2012)

function nacin_my_template( $query ) { if ( ! $query->is_main_query( ) ) return; if ( ! is_page_template( 'my-template.php' ) ) return; $query->set( 'author', '-5' ); $query->set( 'posts_per_page', '25' );

} add_action( 'pre_get_posts',

'nacin_my_template' );

Page 67: You Don't Know Query (WordCamp Netherlands 2012)

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( ).

Page 68: You Don't Know Query (WordCamp Netherlands 2012)

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( )

And Finally

Page 69: You Don't Know Query (WordCamp Netherlands 2012)

Thanks! Questions?

@nacin