You Don't Know Query (WordCamp Netherlands 2012)

  • 29,724 views
Uploaded on

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.

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.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
  • All my doubts are cleared. Thank you
    Are you sure you want to
    Your message goes here
  • For those of you who would love audio/video, have a look at wordpress.tv: http://wordpress.tv/2013/03/15/andrew-nacin-wp_query-wordpress-in-depth
    Are you sure you want to
    Your message goes here
  • Excellent presentation.
    Cleared my confusion about WP_Query
    Are you sure you want to
    Your message goes here
  • Awesome! I really often work with Wordpress. Those were all dark questions I all the time asked my self and googled a lot of times!
    Are you sure you want to
    Your message goes here
  • good slides
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
29,724
On Slideshare
0
From Embeds
0
Number of Embeds
23

Actions

Shares
Downloads
236
Comments
8
Likes
57

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. WordCamp Netherlands 2012
  • 2. Andrew NacinCore Developer of WordPressand Tech Ninja at Audrey Capital@nacin on Twitternacin@wordpress.org
  • 3. You Don’t Know Query
  • 4. What do you know?
  • 5. Conditional Tagsis_author( ), is_home( ), etc.
  • 6. query_posts( )
  • 7. Ways to queryquery_posts( )new WP_Query( )get_posts( )
  • 8. The Loopwhile ( have_posts( ) ) : the_post( );endwhile;
  • 9. A secondary loop$query = new WP_Query( … );while ( $query->have_posts( ) ) : $query->the_post( );endwhile;
  • 10. An array of posts$result = get_posts( … );foreach ( $result as $post_obj ) {}
  • 11. What don’t you know?
  • 12. Every query object has itsown methodsis_author( ) is the same as calling$wp_query->is_author( )
  • 13. function is_author( ) { global $wp_query; return $wp_query->is_author( );}
  • 14. With the regular loopwhile ( have_posts( ) ) : the_post( ); if ( is_author( ) ) echo "An author query.";endwhile;
  • 15. With the regular loopwhile ( have_posts( ) ) : the_post( ); if ( $wp_query->is_author( ) ) echo "An author query.";endwhile;
  • 16. A secondary loop$query = new WP_Query( … );while ( $query->have_posts( ) ) : $query->the_post( ); if ( $query->is_author( ) ) echo "An author query.";endwhile;
  • 17. A secondary loop$query = new WP_Query( … );while ( $query->have_posts( ) ) : $query->the_post( ); if ( $query->is_author( ) ) echo "An author query.";endwhile;
  • 18. A secondary loop$query = new WP_Query( … );while ( $query->have_posts( ) ) : $query->the_post( ); if ( $query->is_author( ) ) echo "An author query.";endwhile;
  • 19. 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( );
  • 20. Why do we call functions likewp_reset_postdata( ) andwp_reset_query( )?What about using query_posts( )?How can you alter a query? Howcan you alter the main query?
  • 21. What is the main query,and why should I care?
  • 22. wp-blog-header.php// Load the WordPress bootstraprequire ./wp-load.php;// Do magicwp( );// Decide which template files to loadrequire WPINC . /template-loader.php;
  • 23. Lets look in the bootstrap:$wp_the_query = new WP_Query();$wp_query =& $wp_the_query;
  • 24. Quick lesson on PHP references$a = 4;$b =& $a;$b = 2;var_dump( $a ); // int(2)$a = 6;var_dump( $b ); // int(6)
  • 25. So:So the real main query is in$wp_the_query.And a live copy of it is stored in$wp_query.
  • 26. wp-blog-header.php// Load the WordPress bootstraprequire ./wp-load.php;// Do magicwp( );// Decide which template files to loadrequire WPINC . /template-loader.php;
  • 27. wp-blog-header.php// Load the WordPress bootstraprequire ./wp-load.php;// Do magicwp( );// Decide which template files to loadrequire WPINC . /template-loader.php;
  • 28. What is that wp( ) call?function wp( $query_vars = ) { global $wp; $wp->main( $query_vars );}
  • 29. Holy $!@?, what justhappened?
  • 30. In the bootstrap:$wp = new WP( );So theres a wp( ) function,and a WP class.
  • 31. class WP { . . . function main( ) { $this->init( ); $this->parse_request( ); $this->send_headers( ); $this->query_posts( ); $this->handle_404( ); $this->register_globals( ); . . .
  • 32. class WP { . . . function main( ) { $this->init( ); $this->parse_request( ); $this->send_headers( ); $this->query_posts( ); $this->handle_404( ); $this->register_globals( ); . . .
  • 33. WP::parse_request( )— Parses the URL using WP_Rewrite— Sets up query variables for WP_QueryWP::query_posts( ) { global $wp_the_query; $wp_the_query->query( $this->query_vars );}
  • 34. Boom.SELECT SQL_CALC_FOUND_ROWS wp_posts.*FROM wp_postsWHERE 1=1 AND wp_posts.post_type = post AND wp_posts.post_status = publishORDER BY wp_posts.post_date DESCLIMIT 0, 10
  • 35. 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;
  • 36. Before we get to the theme,we have your posts.Got it?
  • 37. Then why do we do this?query_posts( author=-5 );get_header( );while( have_posts( ) ) : the_post( );endwhile;get_footer( );
  • 38. Thats running 2* queries!One, the query WordPressthought we wanted.Two, this new one youreactually going to use.
  • 39. * Actually, WP_Querydoesnt run just one query.It usually runs four.
  • 40. 1. Get me my posts: SELECT SQL_CALC_FOUND_ROWS … FROM wp_posts LIMIT 0, 102. How many posts exist? SELECT FOUND_ROWS( )3. Get all metadata for these posts.4. Get all terms for these posts.
  • 41. (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. </aside>
  • 43. PROTIP‘Measure twice, cut once’is bad for performance.
  • 44. Other problems withquery_posts( )
  • 45. Pagination breaks.WordPress calculatedpaging using the query itdid, not the query you did.
  • 46. query_posts( array( author => -5, posts_per_page => 25,) );This will not work well.
  • 47. You easily mess up globals.This can break widgets andmore.
  • 48. query_posts( ) is bad.Do we agree?
  • 49. Introducing pre_get_postsclass WP_Query { . . . function &get_posts() { $this->parse_query(); // Huzzah! do_action_ref_array( pre_get_posts, array( &$this ) ); . . .
  • 50. 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 );
  • 51. Still with us?Good, ‘cause here’s wherethings get complicated.
  • 52. pre_get_posts fires for every postquery: — get_posts( ) — new WP_Query( ) — That random recent posts widget your clientinstalled without you knowing. — Everything.
  • 53. What if I just want it on themain query?
  • 54. $wp_the_query makes atriumphant return.
  • 55. 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 );
  • 56. Hmm. How does this work?$wp_the_query should never be modified. Itholds the main query, forever.$wp_query keeps a live reference to$wp_the_query, unless you usequery_posts( ).
  • 57. query_posts( author=-5 );while ( have_posts( ) ) : the_post( );endwhile;wp_reset_query( );
  • 58. query_posts( author=-5 );while ( have_posts( ) ) : the_post( );endwhile;wp_reset_query( );
  • 59. function query_posts( $query ) { // Break the reference to $wp_the_query unset( $wp_query ); $wp_query =& new WP_Query( $query ); return $wp_query;}
  • 60. query_posts( author=-5 );while ( have_posts( ) ) : the_post( );endwhile;wp_reset_query( );
  • 61. 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( );}
  • 62. 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.
  • 63. 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.
  • 64. What about pagetemplates?
  • 65. /* Template: My Template */query_posts( $query_string . &author=-5&posts_per_page=25 );get_header( );while ( have_posts( ) ) : the_post( );endwhile;
  • 66. 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 );
  • 67. Some LessonsEvery WP_Query object has methods thatmimic the global conditional tags.The global conditional tags apply to$wp_query, the main or current query.$wp_query is always the main query, unlessyou use query_posts( ). Restore it withwp_reset_query( ).
  • 68. And Finallypre_get_posts is a powerful and flexible hook.Just use it properly.Always check if youre modifying the mainquery using $query->is_main_query( )
  • 69. Thanks! Questions?@nacin