• Save
You don’t know query - WordCamp UK Edinburgh 2012
Upcoming SlideShare
Loading in...5
×
 

You don’t know query - WordCamp UK Edinburgh 2012

on

  • 1,147 views

 

Statistics

Views

Total Views
1,147
Views on SlideShare
1,108
Embed Views
39

Actions

Likes
1
Downloads
0
Comments
0

2 Embeds 39

http://eventifier.co 28
https://si0.twimg.com 11

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

You don’t know query - WordCamp UK Edinburgh 2012 You don’t know query - WordCamp UK Edinburgh 2012 Presentation Transcript

  • You Don’t Know Query WordCamp Edinburgh UK 14-15 July 2012
  • Scott Cariss aka Brady• Lead developer at Philosophy Design.• Moderator at WordPress Answers (http://wordpress.stackexchange.com)• WordPress plugin developer and enthusiastscott@philosophydesign.com@l3rady on Twitter
  • You Don’t Know Query
  • What do you know?
  • Conditional Tagsis_author(), is_home(), etc.
  • Who has ever heard of query_posts()?
  • Ways to queryquery_posts()new WP_Query()get_posts()
  • The loopif( have_posts() ) while( have_posts() ): the_post(); endwhile();
  • What don’t you know?
  • Every query object has its own methodsis_author() is the same as calling$wp_query->is_author()
  • function is_author(){ global $wp_query; return $wp_query->is_author();}
  • 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( );
  • But why do we call things likewp_reset_postdata( ) andwp_reset_query( )?What about using query_posts( )?How can you alter a query? What aboutthe main query?
  • What is the main query, and why should I care? Lets dig in
  • wp-blog-header.php// Load the WordPress bootstrap requiredirname( __FILE__ ) . /wp-load.php;// Decide which template files to loadABSPATH . WPINC . /template-loader.php;
  • Let’s look in the bootstrap:$wp_the_query = new WP_Query();$wp_query =& $wp_the_query;
  • Quick lesson on PHP references$a = 4;$b =& $a;$b = 2;var_dump( $a ); // int(2)$a = 6;var_dump( $b ); // int(6)
  • So:The real main query is in$wp_the_query.And a live copy of it is stored in$wp_query
  • wp-blog-header.php// Load the WordPress bootstrap requiredirname( __FILE__ ) . /wp-load.php;// Do magicwp();// Decide which template files to loadABSPATH . WPINC . /template-loader.php;
  • What is that wp() call?function wp( $query_vars = ){ global $wp; $wp->main( $query_vars );}
  • Holy $!@?, what just happened?
  • In the bootstrap:$wp = new WP()So there’s a wp() function, and a WP class.
  • class WP{ ... function main( ) { $this->init( ); $this->parse_request( ); $this->send_headers( ); $this->query_posts( ); $this->handle_404( ); $this->register_globals( ); } ...}
  • class WP{ ... function main( ) { $this->init( ); $this->parse_request( ); $this->send_headers( ); $this->query_posts( ); $this->handle_404( ); $this->register_globals( ); } ...}
  • WP::parse_request( )Parses the URL using WP_RewriteSets up query variables for WP_QueryWP::query_posts( ){ global $wp_the_query; $wp_the_query->query( $this->query_vars );}
  • What do we get?SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROMwp_posts WHERE 1=1 AND wp_posts.post_type = post‘ AND wp_posts.post_status = publish ORDERBY wp_posts.post_date DESC LIMIT 0, 10
  • wp-blog-header.php// Load WordPressdirname( __FILE__ ) . /wp-load.php;// Parse what to query, and query it.wp();// Load the theme.ABSPATH . WPINC . /template-loader.php;
  • Before we get to the theme, we have your posts.Are we clear so far?
  • Then why do we do this?query_posts( author=5 );get_header( );while( have_posts( ) ) : the_post( );endwhile;get_footer( );
  • That’s running 2* queries!One, the query WordPressthought we wanted.Two, this new one you’reactually going to use.
  • * Actually, WP_Query doesnt run just onequery. It usually runs four.
  • 1. Get me my posts: SELECT SQL_CALC_FOUND_ROWS … FROM wp_posts LIMIT 0, 102. How many posts exist? SELECT FOUND_ROWS()3. Pull down all metadata for these posts.4. Pull down all terms for these posts.
  • Instead of query_posts()?We can use this:// In WP::parse_request()$this->query_vars = apply_filters( request, $this->query_vars );
  • We can modify query variables in mid air:function brady_filter_out_author( $qvs ){ if( ! Isset( $qvs*‘author’+ ) ) $qvs*‘author’+ = ‘-5’; return $qvs;}add_filter( “request”, “brady_filter_out_author”);
  • Powerful, but lacks context.Problems:1. Conditional tags don’t work yet.2. Only works on the main query.3. WP_Query is way cooler.
  • Introducing pre_get_postsclass WP_Query{ ... function &get_posts() { $this->parse_query(); // OMG! Conditional tags are available!! do_action_ref_array( pre_get_posts, array( &$this ) ); } ...}
  • Lets kill off query_posts()!function brady_alter_home( $query ){ if ( $query->is_home( ) ) $query->set( author, -5 );}add_action( pre_get_posts, ‘brady_alter_home );
  • Still with us?Good ‘cause here’s where things get hairy.
  • ‘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.
  • What if I just want it on the main query?
  • $wp_the_query makes a triumphant return.
  • Main query only!function brady_alter_home( $query ){ if ( $query->is_home( ) && $wp_the_query === $query ) $query->set( author, -5 );}add_action( pre_get_posts, ‘brady_alter_home );
  • 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().
  • query_posts( author=-5 );while ( have_posts( ) ) : the_post( );endwhile;wp_reset_query( );
  • class WP_Query{ ... function &query_posts( $query ) { // Break the reference to $wp_the_query unset( $wp_query ); $wp_query =& new WP_Query( $query ); ... } ...}
  • query_posts( author=-5 );while ( have_posts( ) ) : the_post( );endwhile;wp_reset_query( );
  • 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( ); ... } ....}
  • 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.
  • Since WordPress 3.3!Rather than:$wp_the_query === $other_query_objectYou‘re able to call:$other_query_object->is_main_query( )
  • Some LessonsEvery 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( ).
  • And finallyrequest is a nice hook. pre_get_posts is more powerful and flexible. Just use it properly.Always check if youre modifying the main query using $query->is_main_query( )$query === $wp_the_query before 3.3
  • Demo
  • Thank you! Any questions?