Top Banner
Getting Crazy Creative with WordPress Queries Drew Jaynes WordCamp Cape Town 2015
41

Getting Creative with WordPress Queries

Apr 16, 2017

Download

Education

DrewAPicture
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: Getting Creative with WordPress Queries

Getting Crazy Creative with WordPress QueriesDrew Jaynes WordCamp Cape Town 2015

Page 2: Getting Creative with WordPress Queries

• Platform Engineer at 10up • Docs Committer for WordPress core • 4.2 Release Lead • Developing with WordPress since 2009 • Slides: http://drewf.us/wcct

Hi, I’m Drew.

Page 3: Getting Creative with WordPress Queries

• Basics • No-Nos • Optimizations • Creative Querying

Topics

Page 4: Getting Creative with WordPress Queries

Query Basics

Page 5: Getting Creative with WordPress Queries

The Loop

if ( have_posts() ) : while ( have_posts() ) : the_post(); ... endwhile; endif;

Page 6: Getting Creative with WordPress Queries

The Loop: Internals

if ( $wp_query->have_posts() ) : while ( $wp_query->have_posts() ) : $wp_query->the_post(); ... endwhile; endif;

Page 7: Getting Creative with WordPress Queries

WP_Query

// Query for the 7 latest, published posts. $query = new WP_Query( array( 'posts_per_page' => 7, 'post_status' => 'publish' ) );

Page 8: Getting Creative with WordPress Queries

WP_Query: SQL

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID 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, 7

Page 9: Getting Creative with WordPress Queries

• WP_Query wrapper • Defaults: Filter suppression • Defaults: No sticky posts • Defaults: No found rows • Array of results vs WP_Query instance

get_posts()

Page 10: Getting Creative with WordPress Queries

get_posts()

// Query for the 7 latest, published posts. $query = get_posts( array( 'posts_per_page' => 7, 'post_status' => 'publish' ) );

Page 11: Getting Creative with WordPress Queries

get_posts(): SQL

SELECT wp_posts.ID 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, 7

Page 12: Getting Creative with WordPress Queries

• Action, not a filter • Fires before the query actually runs • Use query methods intead of top-level functions,

e.g. $query->is_main_query()

pre_get_posts

Page 13: Getting Creative with WordPress Queries

pre_get_posts

/** * Display both posts and pages in the home loop. * * @param WP_Query $query Main WP_Query instance. */ function pages_in_main_query( $query ) { if ( ! is_admin() && is_home() ) { $query->query_vars['post_type'] = array( 'post', 'page' ); } } add_action( 'pre_get_posts', 'pages_in_main_query' );

Page 14: Getting Creative with WordPress Queries

pre_get_posts: Original SQLSELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND ( wp_posts.post_status = ‘publish' OR wp_posts.post_status = ‘private' ) ORDER BY wp_posts.post_date DESC LIMIT 0, 10

Page 15: Getting Creative with WordPress Queries

pre_get_posts: SQLSELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type IN ( 'post', 'page' ) AND ( wp_posts.post_status = ‘publish' OR wp_posts.post_status = ‘private' ) ORDER BY wp_posts.post_date DESC LIMIT 0, 10

Page 16: Getting Creative with WordPress Queries

No-Nos

Page 17: Getting Creative with WordPress Queries

• Completely overrides the main query • Very few valid use cases • Custom page template archives

query_posts()

Page 18: Getting Creative with WordPress Queries

query_posts()query_posts( array( 'post_type' => ‘page’, ‘post_per_page' => 4 ) );

Page 19: Getting Creative with WordPress Queries

posts_per_pageget_posts( array( ‘posts_per_page’ => -1, ‘posts_per_page’ => 100 ) );

Page 20: Getting Creative with WordPress Queries

Optimization

Page 21: Getting Creative with WordPress Queries

• update_post_term_cache • update_post_meta_cache • no_found_rows • fields • posts_per_page

Optimizing WP_Query

Page 22: Getting Creative with WordPress Queries

Optimizing WP_Query$query = new WP_Query( array( 'update_post_term_cache' => false, 'update_post_meta_cache' => false, 'posts_per_page' => 100, 'no_found_rows' => true, 'fields' => 'ids' ) );

Page 23: Getting Creative with WordPress Queries

Creative Querying

Page 24: Getting Creative with WordPress Queries

WP_Query

Page 25: Getting Creative with WordPress Queries

• posts_* filters • pre_get_posts action

WP_Query hooks

Page 26: Getting Creative with WordPress Queries

WP_Query orderby

$posts = get_posts( array( 'posts_per_page' => 15, 'orderby' => array( 'post_date' => 'DESC', 'post_title' => 'ASC' ), ) );

Page 27: Getting Creative with WordPress Queries

WP_Query orderby: SQL

SELECT wp_posts.ID 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, wp_posts.post_title ASC LIMIT 0, 15

Page 28: Getting Creative with WordPress Queries

• Available 4.2+ • Order by independent meta clauses • WP_Meta_Query, WP_User_Query,

WP_Comment_Query

WP_Query orderby: meta clauses

Page 29: Getting Creative with WordPress Queries

WP_Query orderby: meta clauses$posts = get_posts( array( 'meta_query' => array( 'relation' => 'AND', 'state_clause' => array( 'key' => 'state', 'value' => 'Colorado' ), 'city_clause' => array( 'key' => 'city', 'compare' => 'EXISTS' ) ), 'orderby' => array( 'state_clause' => 'ASC', 'city_clause' => 'DESC' ) ) );

Page 30: Getting Creative with WordPress Queries

WP_Query orderby: meta clauses$posts = get_posts( array( 'meta_query' => array( 'relation' => 'AND', 'state_clause' => array( 'key' => 'state', 'value' => 'Colorado' ), 'city_clause' => array( 'key' => 'city', 'compare' => 'EXISTS' ) ), 'orderby' => array( 'state_clause' => 'ASC', 'city_clause' => 'DESC' ) ) );

Page 31: Getting Creative with WordPress Queries

WP_Query orderby: SQLSELECT wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) INNER JOIN wp_postmeta AS mt1 ON ( wp_posts.ID = mt1.post_id ) WHERE 1=1 AND ( ( wp_postmeta.meta_key = ‘state’ AND CAST( wp_postmeta.meta_value AS CHAR ) = ‘Colorado' ) AND mt1.meta_key = ‘city' ) AND wp_posts.post_type = 'post' AND ( ( wp_posts.post_status = 'publish' ) ) GROUP BY wp_posts.ID ORDER BY CAST( mt1.meta_value AS CHAR ) ASC, CAST( wp_postmeta.meta_value AS CHAR ) DESC LIMIT 0, 5

Page 32: Getting Creative with WordPress Queries

WP_User_Query

Page 33: Getting Creative with WordPress Queries

WP_User_Query// Query for users registered on a Tuesday. $query = new WP_User_Query( array( 'date_query' => array( array( 'column' => 'user_registered', 'dayofweek' => 3 // Tuesday ) ), ) );

Page 34: Getting Creative with WordPress Queries

Custom WP_Query Orderby

Page 35: Getting Creative with WordPress Queries

• Order results by a value in a custom table • Adds an additional LEFT JOIN

WP_Query orderby with custom tables

Page 36: Getting Creative with WordPress Queries

Joining Custom Tables: JOIN/** * Join vote totals table to the 'books' custom post type query. * * @param string $join JOIN query clauses. * @param WP_Query $query Current WP_Query instance. * @return string The filtered JOIN clauses. */ function join_votes_table( $join, $query ) { global $wpdb;

if ( ! is_admin() ) { if ( isset( $query->query_vars['post_type'] ) && 'books' == $query->query_vars[‘post_type'] ) { $votes = $wpdb->prefix . 'up_down_post_vote_totals'; $join .= "LEFT JOIN $votes ON $wpdb->posts.ID = $votes.post_id "; } } return $join; } add_filter( 'posts_join', 'join_votes_table', 10, 2 );

Page 37: Getting Creative with WordPress Queries

Joining Custom Tables: ORDERBY/** * Order by vote totals descending, then post date descending. * * @param string $orderby ORDER BY query clauses. * @param WP_Query $query Current WP_Query instance. * @return string The filtered ORDER BY query clauses. */ function orderby_votes_and_date( $orderby, $query ) { global $wpdb;

if ( ! is_admin() ) { if ( isset( $query->query_vars['post_type'] ) && 'books' == $query->query_vars[‘post_type'] ) { $votes = $wpdb->prefix . 'up_down_post_vote_totals'; $orderby = "$votes.vote_count_up DESC, $wpdb->posts.post_date DESC"; } } return $orderby; } add_filter( 'posts_orderby', 'orderby_votes_and_date', 10, 2 );

Page 38: Getting Creative with WordPress Queries

Joining Custom Tables: SQL

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'books' AND ( wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private' ) ORDER BY wp_posts.post_date DESC LIMIT 0, 10

Original SQL:

Page 39: Getting Creative with WordPress Queries

Joining Custom Tables: SQL

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts LEFT JOIN wp_up_down_post_vote_totals ON wp_posts.ID = wp_up_down_post_vote_totals.post_id WHERE 1=1 AND wp_posts.post_type = 'books' AND ( wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private' ) ORDER BY wp_up_down_post_vote_totals.vote_count_up DESC, wp_posts.post_date DESC LIMIT 0, 10

SQL with the JOIN:

Page 41: Getting Creative with WordPress Queries

Questions?

Drew Jaynes | @DrewAPictureSlides: http://drewf.us/wcct