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.stackexcha...
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( ); endw...
But why do we call things likewp_reset_postdata( ) andwp_reset_query( )?What about using query_posts( )?How can you alter ...
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 ...
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 whic...
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( );      $...
class WP{  ...  function main( )  {      $this->init( );      $this->parse_request( );      $this->send_headers( );      $...
WP::parse_request( )Parses the URL using WP_RewriteSets up query variables for WP_QueryWP::query_posts( ){  global $wp_the...
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...
wp-blog-header.php// Load WordPressdirname( __FILE__ ) . /wp-load.php;// Parse what to query, and query it.wp();// Load th...
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 FOUN...
Instead of query_posts()?We can use this:// In WP::parse_request()$this->query_vars = apply_filters(  request, $this->query...
We can modify query variables in mid               air:function brady_filter_out_author( $qvs ){  if( ! Isset( $qvs*‘autho...
Powerful, but lacks context.Problems:1. Conditional tags don’t work yet.2. Only works on the main query.3. WP_Query is way...
Introducing pre_get_postsclass WP_Query{   ...   function &get_posts()   {     $this->parse_query();     // OMG! Condition...
Lets kill off query_posts()!function brady_alter_home( $query ){  if ( $query->is_home( ) )     $query->set( author, -5 );...
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()•   Th...
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 )     $qu...
Hmm. How does this work?$wp_the_query should never be modified. It holds the main query, forever.$wp_query keeps a live ref...
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_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 )...
Calling the_post( )? wp_reset_query( ) will reset  $wp_query and and the globals.Calling $my_query->the_post( )?  wp_reset...
Since WordPress 3.3!Rather than:$wp_the_query === $other_query_objectYou‘re able to call:$other_query_object->is_main_quer...
Some LessonsEvery WP_Query object has methods that mimic  the global conditional tags.The global conditional tags apply to...
And finallyrequest is a nice hook. pre_get_posts is more  powerful and flexible. Just use it properly.Always check if youre...
Demo
Thank you! Any questions?
Upcoming SlideShare
Loading in …5
×

You don’t know query - WordCamp UK Edinburgh 2012

1,254 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,254
On SlideShare
0
From Embeds
0
Number of Embeds
41
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

You don’t know query - WordCamp UK Edinburgh 2012

  1. 1. You Don’t Know Query WordCamp Edinburgh UK 14-15 July 2012
  2. 2. 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
  3. 3. You Don’t Know Query
  4. 4. What do you know?
  5. 5. Conditional Tagsis_author(), is_home(), etc.
  6. 6. Who has ever heard of query_posts()?
  7. 7. Ways to queryquery_posts()new WP_Query()get_posts()
  8. 8. The loopif( have_posts() ) while( have_posts() ): the_post(); endwhile();
  9. 9. What don’t you know?
  10. 10. Every query object has its own methodsis_author() is the same as calling$wp_query->is_author()
  11. 11. function is_author(){ global $wp_query; return $wp_query->is_author();}
  12. 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. 13. 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?
  14. 14. What is the main query, and why should I care? Lets dig in
  15. 15. wp-blog-header.php// Load the WordPress bootstrap requiredirname( __FILE__ ) . /wp-load.php;// Decide which template files to loadABSPATH . WPINC . /template-loader.php;
  16. 16. Let’s look in the bootstrap:$wp_the_query = new WP_Query();$wp_query =& $wp_the_query;
  17. 17. Quick lesson on PHP references$a = 4;$b =& $a;$b = 2;var_dump( $a ); // int(2)$a = 6;var_dump( $b ); // int(6)
  18. 18. So:The real main query is in$wp_the_query.And a live copy of it is stored in$wp_query
  19. 19. 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;
  20. 20. What is that wp() call?function wp( $query_vars = ){ global $wp; $wp->main( $query_vars );}
  21. 21. Holy $!@?, what just happened?
  22. 22. In the bootstrap:$wp = new WP()So there’s a wp() function, and a WP class.
  23. 23. class WP{ ... function main( ) { $this->init( ); $this->parse_request( ); $this->send_headers( ); $this->query_posts( ); $this->handle_404( ); $this->register_globals( ); } ...}
  24. 24. class WP{ ... function main( ) { $this->init( ); $this->parse_request( ); $this->send_headers( ); $this->query_posts( ); $this->handle_404( ); $this->register_globals( ); } ...}
  25. 25. 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 );}
  26. 26. 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
  27. 27. 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;
  28. 28. Before we get to the theme, we have your posts.Are we clear so far?
  29. 29. Then why do we do this?query_posts( author=5 );get_header( );while( have_posts( ) ) : the_post( );endwhile;get_footer( );
  30. 30. That’s running 2* queries!One, the query WordPressthought we wanted.Two, this new one you’reactually going to use.
  31. 31. * Actually, WP_Query doesnt run just onequery. It usually runs four.
  32. 32. 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.
  33. 33. Instead of query_posts()?We can use this:// In WP::parse_request()$this->query_vars = apply_filters( request, $this->query_vars );
  34. 34. 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”);
  35. 35. 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.
  36. 36. 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 ) ); } ...}
  37. 37. 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 );
  38. 38. Still with us?Good ‘cause here’s where things get hairy.
  39. 39. ‘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.
  40. 40. What if I just want it on the main query?
  41. 41. $wp_the_query makes a triumphant return.
  42. 42. 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 );
  43. 43. 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().
  44. 44. query_posts( author=-5 );while ( have_posts( ) ) : the_post( );endwhile;wp_reset_query( );
  45. 45. class WP_Query{ ... function &query_posts( $query ) { // Break the reference to $wp_the_query unset( $wp_query ); $wp_query =& new WP_Query( $query ); ... } ...}
  46. 46. query_posts( author=-5 );while ( have_posts( ) ) : the_post( );endwhile;wp_reset_query( );
  47. 47. 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( ); ... } ....}
  48. 48. 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.
  49. 49. Since WordPress 3.3!Rather than:$wp_the_query === $other_query_objectYou‘re able to call:$other_query_object->is_main_query( )
  50. 50. 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( ).
  51. 51. 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
  52. 52. Demo
  53. 53. Thank you! Any questions?

×