SlideShare une entreprise Scribd logo
1  sur  50
Télécharger pour lire hors ligne
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

Contenu connexe

Tendances

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 2016Colin 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 specqlTatu Tarvainen
 
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 MySQLArti Parab Academics
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介Jace Ju
 
Database API, your new friend
Database API, your new friendDatabase API, your new friend
Database API, your new friendkikoalonsob
 
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 performanceLeon 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. - PHPKonfRafael Dohms
 
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 itRafael Dohms
 

Tendances (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
 

Similaire à 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 queryl3rady
 
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 2011andrewnacin
 
Custom Database Queries in WordPress
Custom Database Queries in WordPressCustom Database Queries in WordPress
Custom Database Queries in WordPresstopher1kenobe
 
[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 2018Adam Tomat
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11Michelangelo 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.noMorten 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 PHPBeneluxMichelangelo van Dam
 
Supercharging WordPress Development - Wordcamp Brighton 2019
Supercharging WordPress Development - Wordcamp Brighton 2019Supercharging WordPress Development - Wordcamp Brighton 2019
Supercharging WordPress Development - Wordcamp Brighton 2019Adam Tomat
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application frameworkDustin 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 webboardtumetr1
 
WordPress for developers - phpday 2011
WordPress for developers -  phpday 2011WordPress for developers -  phpday 2011
WordPress for developers - phpday 2011Maurizio 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
 

Similaire à 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
 

Plus de 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 WorldDrewAPicture
 
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 WorldDrewAPicture
 
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 CoreDrewAPicture
 
Trying Out Tomorrow’s WordPress Today
Trying Out Tomorrow’s WordPress TodayTrying Out Tomorrow’s WordPress Today
Trying Out Tomorrow’s WordPress TodayDrewAPicture
 
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 WordPressDrewAPicture
 
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 StudyDrewAPicture
 
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-lifeDrewAPicture
 
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) HorseDrewAPicture
 
There's a Filter For That
There's a Filter For ThatThere's a Filter For That
There's a Filter For ThatDrewAPicture
 
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 PlaygroundDrewAPicture
 
Anatomy of the WordPress Loop
Anatomy of the WordPress LoopAnatomy of the WordPress Loop
Anatomy of the WordPress LoopDrewAPicture
 

Plus de 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
 

Dernier

Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdf
Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdfLike-prefer-love -hate+verb+ing & silent letters & citizenship text.pdf
Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdfMr Bounab Samir
 
Grade 9 Q4-MELC1-Active and Passive Voice.pptx
Grade 9 Q4-MELC1-Active and Passive Voice.pptxGrade 9 Q4-MELC1-Active and Passive Voice.pptx
Grade 9 Q4-MELC1-Active and Passive Voice.pptxChelloAnnAsuncion2
 
Choosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for ParentsChoosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for Parentsnavabharathschool99
 
GRADE 4 - SUMMATIVE TEST QUARTER 4 ALL SUBJECTS
GRADE 4 - SUMMATIVE TEST QUARTER 4 ALL SUBJECTSGRADE 4 - SUMMATIVE TEST QUARTER 4 ALL SUBJECTS
GRADE 4 - SUMMATIVE TEST QUARTER 4 ALL SUBJECTSJoshuaGantuangco2
 
Inclusivity Essentials_ Creating Accessible Websites for Nonprofits .pdf
Inclusivity Essentials_ Creating Accessible Websites for Nonprofits .pdfInclusivity Essentials_ Creating Accessible Websites for Nonprofits .pdf
Inclusivity Essentials_ Creating Accessible Websites for Nonprofits .pdfTechSoup
 
Barangay Council for the Protection of Children (BCPC) Orientation.pptx
Barangay Council for the Protection of Children (BCPC) Orientation.pptxBarangay Council for the Protection of Children (BCPC) Orientation.pptx
Barangay Council for the Protection of Children (BCPC) Orientation.pptxCarlos105
 
Q4 English4 Week3 PPT Melcnmg-based.pptx
Q4 English4 Week3 PPT Melcnmg-based.pptxQ4 English4 Week3 PPT Melcnmg-based.pptx
Q4 English4 Week3 PPT Melcnmg-based.pptxnelietumpap1
 
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptxMULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptxAnupkumar Sharma
 
4.18.24 Movement Legacies, Reflection, and Review.pptx
4.18.24 Movement Legacies, Reflection, and Review.pptx4.18.24 Movement Legacies, Reflection, and Review.pptx
4.18.24 Movement Legacies, Reflection, and Review.pptxmary850239
 
Science 7 Quarter 4 Module 2: Natural Resources.pptx
Science 7 Quarter 4 Module 2: Natural Resources.pptxScience 7 Quarter 4 Module 2: Natural Resources.pptx
Science 7 Quarter 4 Module 2: Natural Resources.pptxMaryGraceBautista27
 
Gas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxGas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxDr.Ibrahim Hassaan
 
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTiammrhaywood
 
Roles & Responsibilities in Pharmacovigilance
Roles & Responsibilities in PharmacovigilanceRoles & Responsibilities in Pharmacovigilance
Roles & Responsibilities in PharmacovigilanceSamikshaHamane
 
What is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPWhat is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPCeline George
 
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptx
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptxINTRODUCTION TO CATHOLIC CHRISTOLOGY.pptx
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptxHumphrey A Beña
 
Proudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxProudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxthorishapillay1
 
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)lakshayb543
 

Dernier (20)

Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdf
Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdfLike-prefer-love -hate+verb+ing & silent letters & citizenship text.pdf
Like-prefer-love -hate+verb+ing & silent letters & citizenship text.pdf
 
Grade 9 Q4-MELC1-Active and Passive Voice.pptx
Grade 9 Q4-MELC1-Active and Passive Voice.pptxGrade 9 Q4-MELC1-Active and Passive Voice.pptx
Grade 9 Q4-MELC1-Active and Passive Voice.pptx
 
Choosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for ParentsChoosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for Parents
 
GRADE 4 - SUMMATIVE TEST QUARTER 4 ALL SUBJECTS
GRADE 4 - SUMMATIVE TEST QUARTER 4 ALL SUBJECTSGRADE 4 - SUMMATIVE TEST QUARTER 4 ALL SUBJECTS
GRADE 4 - SUMMATIVE TEST QUARTER 4 ALL SUBJECTS
 
Inclusivity Essentials_ Creating Accessible Websites for Nonprofits .pdf
Inclusivity Essentials_ Creating Accessible Websites for Nonprofits .pdfInclusivity Essentials_ Creating Accessible Websites for Nonprofits .pdf
Inclusivity Essentials_ Creating Accessible Websites for Nonprofits .pdf
 
Barangay Council for the Protection of Children (BCPC) Orientation.pptx
Barangay Council for the Protection of Children (BCPC) Orientation.pptxBarangay Council for the Protection of Children (BCPC) Orientation.pptx
Barangay Council for the Protection of Children (BCPC) Orientation.pptx
 
Q4 English4 Week3 PPT Melcnmg-based.pptx
Q4 English4 Week3 PPT Melcnmg-based.pptxQ4 English4 Week3 PPT Melcnmg-based.pptx
Q4 English4 Week3 PPT Melcnmg-based.pptx
 
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptxMULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
 
4.18.24 Movement Legacies, Reflection, and Review.pptx
4.18.24 Movement Legacies, Reflection, and Review.pptx4.18.24 Movement Legacies, Reflection, and Review.pptx
4.18.24 Movement Legacies, Reflection, and Review.pptx
 
YOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptx
YOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptxYOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptx
YOUVE_GOT_EMAIL_PRELIMS_EL_DORADO_2024.pptx
 
Science 7 Quarter 4 Module 2: Natural Resources.pptx
Science 7 Quarter 4 Module 2: Natural Resources.pptxScience 7 Quarter 4 Module 2: Natural Resources.pptx
Science 7 Quarter 4 Module 2: Natural Resources.pptx
 
YOUVE GOT EMAIL_FINALS_EL_DORADO_2024.pptx
YOUVE GOT EMAIL_FINALS_EL_DORADO_2024.pptxYOUVE GOT EMAIL_FINALS_EL_DORADO_2024.pptx
YOUVE GOT EMAIL_FINALS_EL_DORADO_2024.pptx
 
Gas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxGas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptx
 
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
 
Roles & Responsibilities in Pharmacovigilance
Roles & Responsibilities in PharmacovigilanceRoles & Responsibilities in Pharmacovigilance
Roles & Responsibilities in Pharmacovigilance
 
LEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptx
LEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptxLEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptx
LEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptx
 
What is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPWhat is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERP
 
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptx
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptxINTRODUCTION TO CATHOLIC CHRISTOLOGY.pptx
INTRODUCTION TO CATHOLIC CHRISTOLOGY.pptx
 
Proudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxProudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptx
 
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)
Visit to a blind student's school🧑‍🦯🧑‍🦯(community medicine)
 

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