SlideShare a Scribd company logo
Getting Creative
with WordPress Queries
Drew Jaynes
WordCamp Portland 2018
• Chief Bottle Washer

at Sandhills Brewing Development
• WordPress Core Developer
• @DrewAPicture all the places
Drew Jaynes
Slides
http://drewf.us/wcpdx18
• Basics
• No-Nos
• Optimizations
• Creative Querying
Topics
• Lots of code
• Lots of SQL
• No display
Expectations
Query Basics
The Loop
if ( have_posts() ) :
while ( have_posts() ) :
the_post();
...
endwhile;
endif;
The Loop: Internals
if ( $wp_query->have_posts() ) :
while ( $wp_query->have_posts() ) :
$wp_query->the_post();
...
endwhile;
endif;
WP_Query
// Query for the 7 latest, published posts.
$query = new WP_Query( array(
'posts_per_page' => 7,
'post_status' => 'publish'
) );
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
• WP_Query wrapper
• Defaults: Filter suppression
• Defaults: No sticky posts
• Defaults: No found rows
• Array of results vs WP_Query instance
get_posts()
get_posts()
// Query for the 7 latest published posts.
$query = get_posts( array(
'posts_per_page' => 7,
'post_status' => 'publish'
) );
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
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
• Action, not a filter
• $wp_query passed by reference
• Fires before the query actually runs
• Use query methods like $query->is_main_query()
• is_main_query() === _doing_it_wrong()
pre_get_posts
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' );
pre_get_posts: Original 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, 10
pre_get_posts: New SQL
SELECT 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'
)
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10
No-Nos
• Completely overrides the main query
• Very few valid use cases
• Can break pagination (and other stuff)
• wp_reset_query()
• Don’t use it
query_posts()
query_posts()
query_posts( array(
'post_type' => ‘page’,
‘post_per_page' => 4
) );
Optimization
• update_post_term_cache (+1 query)
• update_post_meta_cache (+1 query)
• no_found_rows (+1 query)
• fields
• posts_per_page
Optimizing WP_Query
posts_per_page: Unbounded
get_posts( array(
‘posts_per_page’ => -1,
‘posts_per_page’ => 100
) );
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'
) );
Optimize carefully
Creative Querying
WP_Query
• posts_* filters
• pre_get_posts action
WP_Query hooks
WP_Query multiple orderby
$posts = get_posts( array(
'posts_per_page' => 15,
'orderby' => array(
'post_date' => 'DESC',
'post_title' => 'ASC'
),
) );
WP_Query multiple 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
• Order by independent, named meta clauses
• WP_Meta_Query, WP_User_Query,
WP_Comment_Query
WP_Query orderby: meta clauses
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'
)
) );
WP_Query orderby: SQL
SELECT 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
WP_User_Query
WP_User_Query registered on Tuesday
// Query for users registered on a Tuesday.
$query = new WP_User_Query( array(
‘count_total' => false,
‘orderby' => ‘display_name’,
'date_query' => array(
array(
'column' => 'user_registered',
'dayofweek' => 3 // Tuesday
)
),
) );
WP_User_Query registered on Tuesday: SQL
SELECT wp_users.*.ID FROM wp_users
WHERE 1=1
AND (
DAYOFWEEK( wp_users.user_registered ) = 3
)
ORDER BY
display_name ASC
WP_User_Query lifetime value
// Query for top 10 customers with a lifetime value 1,000+
$query = new WP_User_Query( array(
‘number’ => 10,
‘count_total’ => false, // No pagination.
‘meta_query’ => array(
‘lifetime_value’ => array(
‘key’ => ‘lifetime_value’,
‘compare’ => ‘>=’,
‘value’ => 1000,
‘type’ => ‘DECIMAL’,
),
),
// Order by lifetime value high to low, then name A-Z
'orderby' => array(
‘lifetime_value’ => ‘DESC’,
‘name’ => ‘ASC’,
) );
WP_User_Query lifetime value: SQL
SELECT wp_users.*.ID FROM wp_users
INNER JOIN wp_usermeta ON ( wp_users.ID = wp_usermeta.user_id )
WHERE 1=1
AND (
wp_usermeta.meta_key = ‘lifetime_value’
AND CAST( wp_usermeta.meta_value AS DECIMAL >= ‘1000’ )
ORDER BY
CAST( wp_usermeta.meta_value AS DECIMAL ) DESC,
display_name ASC
LIMIT 0, 10
WP_Term_Query
WP_Term_Query name__like
$query = new WP_Term_Query( array(
'taxonomy' => ‘mascots’,
‘name__like’ => ‘monster’,
‘number’. => 6,
‘order’. => ‘ASC’,
'orderby' => ‘name’,
'fields' => ‘names’,
‘hide_empty' => false,
) );
WP_Term_Query name__like: SQL
SELECT t.name FROM wp_terms AS t
INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id
WHERE
tt.taxonomy IN (‘mascots’) AND t.name LIKE ‘%monster%'
ORDER BY t.name ASC
LIMIT 6
WP_Query: Custom Orderby
• Order results by a value in a custom table
• Adds an additional LEFT JOIN
WP_Query orderby with custom tables
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 );
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 );
Joining Custom Tables: Original 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
Joining Custom Tables: SQL with JOIN
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
• Debug Bar
• WordPress Developer Hub
• WP_Query (Code Reference)
• Trunk wp-includes/
Plugins & Resources
Questions?
Drew Jaynes | @DrewAPicture
Slides: http://drewf.us/wcpdx18

More Related Content

What's hot

Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
Simon Willison
 
Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016
Colin O'Dell
 
WP_Query, pre_get_posts, and eliminating query_posts()
WP_Query, pre_get_posts, and eliminating query_posts()WP_Query, pre_get_posts, and eliminating query_posts()
WP_Query, pre_get_posts, and eliminating query_posts()
Erick Hitter
 
Scrap your query boilerplate with specql
Scrap your query boilerplate with specqlScrap your query boilerplate with specql
Scrap your query boilerplate with specql
Tatu Tarvainen
 
Schemadoc
SchemadocSchemadoc
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
Michelangelo van Dam
 
FYBSC IT Web Programming Unit V Advanced PHP and MySQL
FYBSC IT Web Programming Unit V  Advanced PHP and MySQLFYBSC IT Web Programming Unit V  Advanced PHP and MySQL
FYBSC IT Web Programming Unit V Advanced PHP and MySQL
Arti Parab Academics
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
Jace Ju
 
Database API, your new friend
Database API, your new friendDatabase API, your new friend
Database API, your new friendkikoalonsob
 
Recursive Query Throwdown
Recursive Query ThrowdownRecursive Query Throwdown
Recursive Query Throwdown
Karwin Software Solutions LLC
 
Web осень 2012 лекция 6
Web осень 2012 лекция 6Web осень 2012 лекция 6
Web осень 2012 лекция 6Technopark
 
Developing applications for performance
Developing applications for performanceDeveloping applications for performance
Developing applications for performance
Leon Fayer
 
Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6Technopark
 
What's new in the Drupal 7 API?
What's new in the Drupal 7 API?What's new in the Drupal 7 API?
What's new in the Drupal 7 API?
Alexandru Badiu
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
Rafael Dohms
 
Mentor Your Indexes
Mentor Your IndexesMentor Your Indexes
Mentor Your Indexes
Karwin Software Solutions LLC
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
Rafael Dohms
 
Pagination in PHP
Pagination in PHPPagination in PHP
Pagination in PHP
Vineet Kumar Saini
 

What's hot (20)

Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
 
Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016
 
WP_Query, pre_get_posts, and eliminating query_posts()
WP_Query, pre_get_posts, and eliminating query_posts()WP_Query, pre_get_posts, and eliminating query_posts()
WP_Query, pre_get_posts, and eliminating query_posts()
 
Scrap your query boilerplate with specql
Scrap your query boilerplate with specqlScrap your query boilerplate with specql
Scrap your query boilerplate with specql
 
Php summary
Php summaryPhp summary
Php summary
 
Schemadoc
SchemadocSchemadoc
Schemadoc
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
FYBSC IT Web Programming Unit V Advanced PHP and MySQL
FYBSC IT Web Programming Unit V  Advanced PHP and MySQLFYBSC IT Web Programming Unit V  Advanced PHP and MySQL
FYBSC IT Web Programming Unit V Advanced PHP and MySQL
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
 
Database API, your new friend
Database API, your new friendDatabase API, your new friend
Database API, your new friend
 
Mysql & Php
Mysql & PhpMysql & Php
Mysql & Php
 
Recursive Query Throwdown
Recursive Query ThrowdownRecursive Query Throwdown
Recursive Query Throwdown
 
Web осень 2012 лекция 6
Web осень 2012 лекция 6Web осень 2012 лекция 6
Web осень 2012 лекция 6
 
Developing applications for performance
Developing applications for performanceDeveloping applications for performance
Developing applications for performance
 
Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6
 
What's new in the Drupal 7 API?
What's new in the Drupal 7 API?What's new in the Drupal 7 API?
What's new in the Drupal 7 API?
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
 
Mentor Your Indexes
Mentor Your IndexesMentor Your Indexes
Mentor Your Indexes
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
 
Pagination in PHP
Pagination in PHPPagination in PHP
Pagination in PHP
 

Similar to Getting Creative with WordPress Queries, Again

You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)
andrewnacin
 
The Query the Whole Query and Nothing but the Query
The Query the Whole Query and Nothing but the QueryThe Query the Whole Query and Nothing but the Query
The Query the Whole Query and Nothing but the QueryChris Olbekson
 
WordPress London 16 May 2012 - You don’t know query
WordPress London 16 May 2012 - You don’t know queryWordPress London 16 May 2012 - You don’t know query
WordPress London 16 May 2012 - You don’t know query
l3rady
 
You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011
andrewnacin
 
Custom Database Queries in WordPress
Custom Database Queries in WordPressCustom Database Queries in WordPress
Custom Database Queries in WordPress
topher1kenobe
 
[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018
Adam Tomat
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
Michelangelo van Dam
 
Can WordPress really do that? A case study of vierderduer.no
Can WordPress really do that? A case study of vierderduer.noCan WordPress really do that? A case study of vierderduer.no
Can WordPress really do that? A case study of vierderduer.no
Morten Rand-Hendriksen
 
Wordcamp Fayetteville Pods Presentation (PDF)
Wordcamp Fayetteville Pods Presentation (PDF)Wordcamp Fayetteville Pods Presentation (PDF)
Wordcamp Fayetteville Pods Presentation (PDF)mpvanwinkle
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
Michelangelo van Dam
 
Victoria wordpress
Victoria wordpressVictoria wordpress
Victoria wordpress
Flynn O'Connor
 
Supercharging WordPress Development - Wordcamp Brighton 2019
Supercharging WordPress Development - Wordcamp Brighton 2019Supercharging WordPress Development - Wordcamp Brighton 2019
Supercharging WordPress Development - Wordcamp Brighton 2019
Adam Tomat
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application framework
Dustin Filippini
 
DrupalCamp Foz - Novas APIs Drupal 7
DrupalCamp Foz - Novas APIs Drupal 7DrupalCamp Foz - Novas APIs Drupal 7
DrupalCamp Foz - Novas APIs Drupal 7chuvainc
 
PHP webboard
PHP webboardPHP webboard
PHP webboard
tumetr1
 
WordPress for developers - phpday 2011
WordPress for developers -  phpday 2011WordPress for developers -  phpday 2011
WordPress for developers - phpday 2011
Maurizio Pelizzone
 
Propel sfugmd
Propel sfugmdPropel sfugmd
Propel sfugmdiKlaus
 
Ex[1].3 php db connectivity
Ex[1].3 php db connectivityEx[1].3 php db connectivity
Ex[1].3 php db connectivityMouli Chandira
 

Similar to Getting Creative with WordPress Queries, Again (20)

You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)
 
The Query the Whole Query and Nothing but the Query
The Query the Whole Query and Nothing but the QueryThe Query the Whole Query and Nothing but the Query
The Query the Whole Query and Nothing but the Query
 
WordPress London 16 May 2012 - You don’t know query
WordPress London 16 May 2012 - You don’t know queryWordPress London 16 May 2012 - You don’t know query
WordPress London 16 May 2012 - You don’t know query
 
You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011
 
Custom Database Queries in WordPress
Custom Database Queries in WordPressCustom Database Queries in WordPress
Custom Database Queries in WordPress
 
[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Can WordPress really do that? A case study of vierderduer.no
Can WordPress really do that? A case study of vierderduer.noCan WordPress really do that? A case study of vierderduer.no
Can WordPress really do that? A case study of vierderduer.no
 
Wordcamp Fayetteville Pods Presentation (PDF)
Wordcamp Fayetteville Pods Presentation (PDF)Wordcamp Fayetteville Pods Presentation (PDF)
Wordcamp Fayetteville Pods Presentation (PDF)
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Victoria wordpress
Victoria wordpressVictoria wordpress
Victoria wordpress
 
Supercharging WordPress Development - Wordcamp Brighton 2019
Supercharging WordPress Development - Wordcamp Brighton 2019Supercharging WordPress Development - Wordcamp Brighton 2019
Supercharging WordPress Development - Wordcamp Brighton 2019
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application framework
 
DrupalCamp Foz - Novas APIs Drupal 7
DrupalCamp Foz - Novas APIs Drupal 7DrupalCamp Foz - Novas APIs Drupal 7
DrupalCamp Foz - Novas APIs Drupal 7
 
Mysocial databasequeries
Mysocial databasequeriesMysocial databasequeries
Mysocial databasequeries
 
Mysocial databasequeries
Mysocial databasequeriesMysocial databasequeries
Mysocial databasequeries
 
PHP webboard
PHP webboardPHP webboard
PHP webboard
 
WordPress for developers - phpday 2011
WordPress for developers -  phpday 2011WordPress for developers -  phpday 2011
WordPress for developers - phpday 2011
 
Propel sfugmd
Propel sfugmdPropel sfugmd
Propel sfugmd
 
Ex[1].3 php db connectivity
Ex[1].3 php db connectivityEx[1].3 php db connectivity
Ex[1].3 php db connectivity
 

More from DrewAPicture

WordPress Development in a Modern PHP World
WordPress Development in a Modern PHP WorldWordPress Development in a Modern PHP World
WordPress Development in a Modern PHP World
DrewAPicture
 
WordPress Development in a Modern PHP World
WordPress Development in a Modern PHP WorldWordPress Development in a Modern PHP World
WordPress Development in a Modern PHP World
DrewAPicture
 
How to Win Friends and Influence WordPress Core
How to Win Friends and Influence WordPress CoreHow to Win Friends and Influence WordPress Core
How to Win Friends and Influence WordPress Core
DrewAPicture
 
Trying Out Tomorrow’s WordPress Today
Trying Out Tomorrow’s WordPress TodayTrying Out Tomorrow’s WordPress Today
Trying Out Tomorrow’s WordPress Today
DrewAPicture
 
It Takes a Village to Make WordPress
It Takes a Village to Make WordPressIt Takes a Village to Make WordPress
It Takes a Village to Make WordPress
DrewAPicture
 
Setting Up WordPress: A NUX Case Study
Setting Up WordPress: A NUX Case StudySetting Up WordPress: A NUX Case Study
Setting Up WordPress: A NUX Case Study
DrewAPicture
 
Core Docs: Sentencing WordPress to 11-years-to-life
Core Docs: Sentencing WordPress to 11-years-to-lifeCore Docs: Sentencing WordPress to 11-years-to-life
Core Docs: Sentencing WordPress to 11-years-to-life
DrewAPicture
 
Putting the (docs) Cart Before the (standards) Horse
Putting the (docs) Cart Before the (standards) HorsePutting the (docs) Cart Before the (standards) Horse
Putting the (docs) Cart Before the (standards) Horse
DrewAPicture
 
There's a Filter For That
There's a Filter For ThatThere's a Filter For That
There's a Filter For That
DrewAPicture
 
Customizer-ing Theme Options: A Visual Playground
Customizer-ing Theme Options: A Visual PlaygroundCustomizer-ing Theme Options: A Visual Playground
Customizer-ing Theme Options: A Visual Playground
DrewAPicture
 
Anatomy of the WordPress Loop
Anatomy of the WordPress LoopAnatomy of the WordPress Loop
Anatomy of the WordPress Loop
DrewAPicture
 

More from DrewAPicture (11)

WordPress Development in a Modern PHP World
WordPress Development in a Modern PHP WorldWordPress Development in a Modern PHP World
WordPress Development in a Modern PHP World
 
WordPress Development in a Modern PHP World
WordPress Development in a Modern PHP WorldWordPress Development in a Modern PHP World
WordPress Development in a Modern PHP World
 
How to Win Friends and Influence WordPress Core
How to Win Friends and Influence WordPress CoreHow to Win Friends and Influence WordPress Core
How to Win Friends and Influence WordPress Core
 
Trying Out Tomorrow’s WordPress Today
Trying Out Tomorrow’s WordPress TodayTrying Out Tomorrow’s WordPress Today
Trying Out Tomorrow’s WordPress Today
 
It Takes a Village to Make WordPress
It Takes a Village to Make WordPressIt Takes a Village to Make WordPress
It Takes a Village to Make WordPress
 
Setting Up WordPress: A NUX Case Study
Setting Up WordPress: A NUX Case StudySetting Up WordPress: A NUX Case Study
Setting Up WordPress: A NUX Case Study
 
Core Docs: Sentencing WordPress to 11-years-to-life
Core Docs: Sentencing WordPress to 11-years-to-lifeCore Docs: Sentencing WordPress to 11-years-to-life
Core Docs: Sentencing WordPress to 11-years-to-life
 
Putting the (docs) Cart Before the (standards) Horse
Putting the (docs) Cart Before the (standards) HorsePutting the (docs) Cart Before the (standards) Horse
Putting the (docs) Cart Before the (standards) Horse
 
There's a Filter For That
There's a Filter For ThatThere's a Filter For That
There's a Filter For That
 
Customizer-ing Theme Options: A Visual Playground
Customizer-ing Theme Options: A Visual PlaygroundCustomizer-ing Theme Options: A Visual Playground
Customizer-ing Theme Options: A Visual Playground
 
Anatomy of the WordPress Loop
Anatomy of the WordPress LoopAnatomy of the WordPress Loop
Anatomy of the WordPress Loop
 

Recently uploaded

The Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptxThe Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptx
DhatriParmar
 
The Diamonds of 2023-2024 in the IGRA collection
The Diamonds of 2023-2024 in the IGRA collectionThe Diamonds of 2023-2024 in the IGRA collection
The Diamonds of 2023-2024 in the IGRA collection
Israel Genealogy Research Association
 
S1-Introduction-Biopesticides in ICM.pptx
S1-Introduction-Biopesticides in ICM.pptxS1-Introduction-Biopesticides in ICM.pptx
S1-Introduction-Biopesticides in ICM.pptx
tarandeep35
 
1.4 modern child centered education - mahatma gandhi-2.pptx
1.4 modern child centered education - mahatma gandhi-2.pptx1.4 modern child centered education - mahatma gandhi-2.pptx
1.4 modern child centered education - mahatma gandhi-2.pptx
JosvitaDsouza2
 
The basics of sentences session 5pptx.pptx
The basics of sentences session 5pptx.pptxThe basics of sentences session 5pptx.pptx
The basics of sentences session 5pptx.pptx
heathfieldcps1
 
How libraries can support authors with open access requirements for UKRI fund...
How libraries can support authors with open access requirements for UKRI fund...How libraries can support authors with open access requirements for UKRI fund...
How libraries can support authors with open access requirements for UKRI fund...
Jisc
 
Digital Artifact 2 - Investigating Pavilion Designs
Digital Artifact 2 - Investigating Pavilion DesignsDigital Artifact 2 - Investigating Pavilion Designs
Digital Artifact 2 - Investigating Pavilion Designs
chanes7
 
Multithreading_in_C++ - std::thread, race condition
Multithreading_in_C++ - std::thread, race conditionMultithreading_in_C++ - std::thread, race condition
Multithreading_in_C++ - std::thread, race condition
Mohammed Sikander
 
Synthetic Fiber Construction in lab .pptx
Synthetic Fiber Construction in lab .pptxSynthetic Fiber Construction in lab .pptx
Synthetic Fiber Construction in lab .pptx
Pavel ( NSTU)
 
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
MysoreMuleSoftMeetup
 
The Diamond Necklace by Guy De Maupassant.pptx
The Diamond Necklace by Guy De Maupassant.pptxThe Diamond Necklace by Guy De Maupassant.pptx
The Diamond Necklace by Guy De Maupassant.pptx
DhatriParmar
 
Unit 2- Research Aptitude (UGC NET Paper I).pdf
Unit 2- Research Aptitude (UGC NET Paper I).pdfUnit 2- Research Aptitude (UGC NET Paper I).pdf
Unit 2- Research Aptitude (UGC NET Paper I).pdf
Thiyagu K
 
Unit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdfUnit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdf
Thiyagu K
 
Normal Labour/ Stages of Labour/ Mechanism of Labour
Normal Labour/ Stages of Labour/ Mechanism of LabourNormal Labour/ Stages of Labour/ Mechanism of Labour
Normal Labour/ Stages of Labour/ Mechanism of Labour
Wasim Ak
 
Chapter 3 - Islamic Banking Products and Services.pptx
Chapter 3 - Islamic Banking Products and Services.pptxChapter 3 - Islamic Banking Products and Services.pptx
Chapter 3 - Islamic Banking Products and Services.pptx
Mohd Adib Abd Muin, Senior Lecturer at Universiti Utara Malaysia
 
Francesca Gottschalk - How can education support child empowerment.pptx
Francesca Gottschalk - How can education support child empowerment.pptxFrancesca Gottschalk - How can education support child empowerment.pptx
Francesca Gottschalk - How can education support child empowerment.pptx
EduSkills OECD
 
June 3, 2024 Anti-Semitism Letter Sent to MIT President Kornbluth and MIT Cor...
June 3, 2024 Anti-Semitism Letter Sent to MIT President Kornbluth and MIT Cor...June 3, 2024 Anti-Semitism Letter Sent to MIT President Kornbluth and MIT Cor...
June 3, 2024 Anti-Semitism Letter Sent to MIT President Kornbluth and MIT Cor...
Levi Shapiro
 
Overview on Edible Vaccine: Pros & Cons with Mechanism
Overview on Edible Vaccine: Pros & Cons with MechanismOverview on Edible Vaccine: Pros & Cons with Mechanism
Overview on Edible Vaccine: Pros & Cons with Mechanism
DeeptiGupta154
 
"Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe..."Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe...
SACHIN R KONDAGURI
 
Pride Month Slides 2024 David Douglas School District
Pride Month Slides 2024 David Douglas School DistrictPride Month Slides 2024 David Douglas School District
Pride Month Slides 2024 David Douglas School District
David Douglas School District
 

Recently uploaded (20)

The Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptxThe Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptx
 
The Diamonds of 2023-2024 in the IGRA collection
The Diamonds of 2023-2024 in the IGRA collectionThe Diamonds of 2023-2024 in the IGRA collection
The Diamonds of 2023-2024 in the IGRA collection
 
S1-Introduction-Biopesticides in ICM.pptx
S1-Introduction-Biopesticides in ICM.pptxS1-Introduction-Biopesticides in ICM.pptx
S1-Introduction-Biopesticides in ICM.pptx
 
1.4 modern child centered education - mahatma gandhi-2.pptx
1.4 modern child centered education - mahatma gandhi-2.pptx1.4 modern child centered education - mahatma gandhi-2.pptx
1.4 modern child centered education - mahatma gandhi-2.pptx
 
The basics of sentences session 5pptx.pptx
The basics of sentences session 5pptx.pptxThe basics of sentences session 5pptx.pptx
The basics of sentences session 5pptx.pptx
 
How libraries can support authors with open access requirements for UKRI fund...
How libraries can support authors with open access requirements for UKRI fund...How libraries can support authors with open access requirements for UKRI fund...
How libraries can support authors with open access requirements for UKRI fund...
 
Digital Artifact 2 - Investigating Pavilion Designs
Digital Artifact 2 - Investigating Pavilion DesignsDigital Artifact 2 - Investigating Pavilion Designs
Digital Artifact 2 - Investigating Pavilion Designs
 
Multithreading_in_C++ - std::thread, race condition
Multithreading_in_C++ - std::thread, race conditionMultithreading_in_C++ - std::thread, race condition
Multithreading_in_C++ - std::thread, race condition
 
Synthetic Fiber Construction in lab .pptx
Synthetic Fiber Construction in lab .pptxSynthetic Fiber Construction in lab .pptx
Synthetic Fiber Construction in lab .pptx
 
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
 
The Diamond Necklace by Guy De Maupassant.pptx
The Diamond Necklace by Guy De Maupassant.pptxThe Diamond Necklace by Guy De Maupassant.pptx
The Diamond Necklace by Guy De Maupassant.pptx
 
Unit 2- Research Aptitude (UGC NET Paper I).pdf
Unit 2- Research Aptitude (UGC NET Paper I).pdfUnit 2- Research Aptitude (UGC NET Paper I).pdf
Unit 2- Research Aptitude (UGC NET Paper I).pdf
 
Unit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdfUnit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdf
 
Normal Labour/ Stages of Labour/ Mechanism of Labour
Normal Labour/ Stages of Labour/ Mechanism of LabourNormal Labour/ Stages of Labour/ Mechanism of Labour
Normal Labour/ Stages of Labour/ Mechanism of Labour
 
Chapter 3 - Islamic Banking Products and Services.pptx
Chapter 3 - Islamic Banking Products and Services.pptxChapter 3 - Islamic Banking Products and Services.pptx
Chapter 3 - Islamic Banking Products and Services.pptx
 
Francesca Gottschalk - How can education support child empowerment.pptx
Francesca Gottschalk - How can education support child empowerment.pptxFrancesca Gottschalk - How can education support child empowerment.pptx
Francesca Gottschalk - How can education support child empowerment.pptx
 
June 3, 2024 Anti-Semitism Letter Sent to MIT President Kornbluth and MIT Cor...
June 3, 2024 Anti-Semitism Letter Sent to MIT President Kornbluth and MIT Cor...June 3, 2024 Anti-Semitism Letter Sent to MIT President Kornbluth and MIT Cor...
June 3, 2024 Anti-Semitism Letter Sent to MIT President Kornbluth and MIT Cor...
 
Overview on Edible Vaccine: Pros & Cons with Mechanism
Overview on Edible Vaccine: Pros & Cons with MechanismOverview on Edible Vaccine: Pros & Cons with Mechanism
Overview on Edible Vaccine: Pros & Cons with Mechanism
 
"Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe..."Protectable subject matters, Protection in biotechnology, Protection of othe...
"Protectable subject matters, Protection in biotechnology, Protection of othe...
 
Pride Month Slides 2024 David Douglas School District
Pride Month Slides 2024 David Douglas School DistrictPride Month Slides 2024 David Douglas School District
Pride Month Slides 2024 David Douglas School District
 

Getting Creative with WordPress Queries, Again

  • 1. Getting Creative with WordPress Queries Drew Jaynes WordCamp Portland 2018
  • 2. • Chief Bottle Washer
 at Sandhills Brewing Development • WordPress Core Developer • @DrewAPicture all the places Drew Jaynes
  • 4. • Basics • No-Nos • Optimizations • Creative Querying Topics
  • 5. • Lots of code • Lots of SQL • No display Expectations
  • 7. The Loop if ( have_posts() ) : while ( have_posts() ) : the_post(); ... endwhile; endif;
  • 8. The Loop: Internals if ( $wp_query->have_posts() ) : while ( $wp_query->have_posts() ) : $wp_query->the_post(); ... endwhile; endif;
  • 9. WP_Query // Query for the 7 latest, published posts. $query = new WP_Query( array( 'posts_per_page' => 7, 'post_status' => 'publish' ) );
  • 10. 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
  • 11. • WP_Query wrapper • Defaults: Filter suppression • Defaults: No sticky posts • Defaults: No found rows • Array of results vs WP_Query instance get_posts()
  • 12. get_posts() // Query for the 7 latest published posts. $query = get_posts( array( 'posts_per_page' => 7, 'post_status' => 'publish' ) );
  • 13. 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
  • 14. 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
  • 15. • Action, not a filter • $wp_query passed by reference • Fires before the query actually runs • Use query methods like $query->is_main_query() • is_main_query() === _doing_it_wrong() pre_get_posts
  • 16. 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' );
  • 17. pre_get_posts: Original 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, 10
  • 18. pre_get_posts: New SQL SELECT 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' ) ORDER BY wp_posts.post_date DESC LIMIT 0, 10
  • 20. • Completely overrides the main query • Very few valid use cases • Can break pagination (and other stuff) • wp_reset_query() • Don’t use it query_posts()
  • 21. query_posts() query_posts( array( 'post_type' => ‘page’, ‘post_per_page' => 4 ) );
  • 23. • update_post_term_cache (+1 query) • update_post_meta_cache (+1 query) • no_found_rows (+1 query) • fields • posts_per_page Optimizing WP_Query
  • 24. posts_per_page: Unbounded get_posts( array( ‘posts_per_page’ => -1, ‘posts_per_page’ => 100 ) );
  • 25. 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' ) );
  • 29. • posts_* filters • pre_get_posts action WP_Query hooks
  • 30. WP_Query multiple orderby $posts = get_posts( array( 'posts_per_page' => 15, 'orderby' => array( 'post_date' => 'DESC', 'post_title' => 'ASC' ), ) );
  • 31. WP_Query multiple 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
  • 32. • Order by independent, named meta clauses • WP_Meta_Query, WP_User_Query, WP_Comment_Query WP_Query orderby: meta clauses
  • 33. 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' ) ) );
  • 34. WP_Query orderby: SQL SELECT 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
  • 36. WP_User_Query registered on Tuesday // Query for users registered on a Tuesday. $query = new WP_User_Query( array( ‘count_total' => false, ‘orderby' => ‘display_name’, 'date_query' => array( array( 'column' => 'user_registered', 'dayofweek' => 3 // Tuesday ) ), ) );
  • 37. WP_User_Query registered on Tuesday: SQL SELECT wp_users.*.ID FROM wp_users WHERE 1=1 AND ( DAYOFWEEK( wp_users.user_registered ) = 3 ) ORDER BY display_name ASC
  • 38. WP_User_Query lifetime value // Query for top 10 customers with a lifetime value 1,000+ $query = new WP_User_Query( array( ‘number’ => 10, ‘count_total’ => false, // No pagination. ‘meta_query’ => array( ‘lifetime_value’ => array( ‘key’ => ‘lifetime_value’, ‘compare’ => ‘>=’, ‘value’ => 1000, ‘type’ => ‘DECIMAL’, ), ), // Order by lifetime value high to low, then name A-Z 'orderby' => array( ‘lifetime_value’ => ‘DESC’, ‘name’ => ‘ASC’, ) );
  • 39. WP_User_Query lifetime value: SQL SELECT wp_users.*.ID FROM wp_users INNER JOIN wp_usermeta ON ( wp_users.ID = wp_usermeta.user_id ) WHERE 1=1 AND ( wp_usermeta.meta_key = ‘lifetime_value’ AND CAST( wp_usermeta.meta_value AS DECIMAL >= ‘1000’ ) ORDER BY CAST( wp_usermeta.meta_value AS DECIMAL ) DESC, display_name ASC LIMIT 0, 10
  • 41. WP_Term_Query name__like $query = new WP_Term_Query( array( 'taxonomy' => ‘mascots’, ‘name__like’ => ‘monster’, ‘number’. => 6, ‘order’. => ‘ASC’, 'orderby' => ‘name’, 'fields' => ‘names’, ‘hide_empty' => false, ) );
  • 42. WP_Term_Query name__like: SQL SELECT t.name FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy IN (‘mascots’) AND t.name LIKE ‘%monster%' ORDER BY t.name ASC LIMIT 6
  • 44. • Order results by a value in a custom table • Adds an additional LEFT JOIN WP_Query orderby with custom tables
  • 45. 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 );
  • 46. 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 );
  • 47. Joining Custom Tables: Original 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
  • 48. Joining Custom Tables: SQL with JOIN 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
  • 49. • Debug Bar • WordPress Developer Hub • WP_Query (Code Reference) • Trunk wp-includes/ Plugins & Resources
  • 50. Questions? Drew Jaynes | @DrewAPicture Slides: http://drewf.us/wcpdx18