You don’t know query - WordCamp UK Edinburgh 2012

1,102
-1

Published on

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

No Downloads
Views
Total Views
1,102
On Slideshare
0
From Embeds
0
Number of Embeds
1
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?

×