wordpress queries - the right way

Post on 08-May-2015

3.524 Views

Category:

Art & Photos

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

This is a presentation for the November WordPress Melbourne meetup. It shows how to modify your main WordPress query the right way, using the pre_get_posts hook, rather than using query_posts() or even WP_Query().

TRANSCRIPT

WordPress Queries-the right way

#wpmelbAnthony Hortin

@maddisondesigns

How you’re probably querying

query_posts()

get_posts()

new WP_Query()

You’re doing it wrong!

if ( have_posts() ) :

while ( have_posts() ) :

the_post();

endwhile;

endif;

The Loop

if ( have_posts() ) // Determines if there’s anything to iterate while ( have_posts() ) :

the_post();

endwhile;

endif;

The Loop

if ( have_posts() )

while ( have_posts() ) : // Sets up globals & continues iteration the_post();

endwhile;

endif;

The Loop

Anatomy of a WordPress Page

The Main Query

// Loads the WordPress bootstrap// ie. Sets the ABSPATH constant.// Loads the wp-config.php file etc.

require_once( dirname(__FILE__) . '/wp-load.php' );

wp();

// Decide which template files to load// ie. archive.php, index.php etc

require_once( ABSPATH . WPINC . '/template-loader.php' );

wp-blog-header.php

// Loads the WordPress bootstrap// ie. Sets the ABSPATH constant.// Loads the wp-config.php file etc.

require_once( dirname(__FILE__) . '/wp-load.php' );

wp();

// Decide which template files to load// ie. archive.php, index.php etc

require_once( ABSPATH . WPINC . '/template-loader.php' );

wp-blog-header.php

// Loads the WordPress bootstrap// ie. Sets the ABSPATH constant.// Loads the wp-config.php file etc.

require_once( dirname(__FILE__) . '/wp-load.php' );

wp();

// Decide which template files to load// ie. archive.php, index.php etc

require_once( ABSPATH . WPINC . '/template-loader.php' );

wp-blog-header.php

// Loads the WordPress bootstrap// ie. Sets the ABSPATH constant.// Loads the wp-config.php file etc.

require_once( dirname(__FILE__) . '/wp-load.php' );

// Does ALL THE THINGS!

wp();

// Decide which template files to load// ie. archive.php, index.php etc

require_once( ABSPATH . WPINC . '/template-loader.php' );

wp-blog-header.php

What is wp()?

wp();

- Parses the URL & runs it through WP_Rewrite

- Sets up query variables for WP_Query

- Runs the query

What is wp()?

wp();

- Parses the URL & runs it through WP_Rewrite

- Sets up query variables for WP_Query

- Runs the query

What is wp()?

wp();

- Parses the URL & runs it through WP_Rewrite

- Sets up query variables for WP_Query

- Runs the query

What is wp()?

wp();

- Parses the URL & runs it through WP_Rewrite

- Sets up query variables for WP_Query

- Runs the query

So, what does this mean?

It means...

Before the theme is even loaded,

WordPress already has your Posts!

Mind == Blown!

In the bootstrap

$wp_the_query = new WP_Query();

$wp_query =& $wp_the_query;

In the bootstrap

// Holds the real main query.// It should never be modified

$wp_the_query

// A live reference to the main query

$wp_query

In the bootstrap

// Holds the real main query.// It should never be modified

$wp_the_query

// A live reference to the main query

$wp_query

Back to our queries...

query_posts()

get_posts()

new WP_Query()

All three create new WP_Query objects

query_posts()goes one step further though

query_posts()

function &query_posts($query) {

unset($GLOBALS['wp_query']);

$GLOBALS['wp_query'] = new WP_Query();

return $GLOBALS['wp_query']->query($query);

}

query_posts()

function &query_posts($query) { // Destroys the Global $wp_query variable! unset($GLOBALS['wp_query']);

$GLOBALS['wp_query'] = new WP_Query();

return $GLOBALS['wp_query']->query($query);

}

query_posts()

function &query_posts($query) {

unset($GLOBALS['wp_query']); // Creates new $wp_query variable $GLOBALS['wp_query'] = new WP_Query();

return $GLOBALS['wp_query']->query($query);

}

I’m sure you’ve all done this...

get_header();

query_posts( 'cat=-1,-2,-3' );

while( have_posts() ) :

the_post();

endwhile;

wp_reset_query();

get_footer();

That’s running 2* queries!

It’s running the query WordPress

thinks you want.

It’s then running your new query

you actually want.

That’s running 2* queries!

In actual fact, WP_Querydoesn’t just run one query.It runs four!

So, that means your template

is actually running eight queries!

*

Don’t forget to reset

// Restores the $wp_query reference to $wp_the_query

// Resets the globals

wp_reset_query();

// Resets the globals

wp_reset_postdata();

There’s a better way

Say hello to pre_get_posts

[From the Codex]

The pre_get_posts action gives developers access to the $query object by reference.(any changes you make to $query are made directly to the original object)

Say hello to pre_get_posts

What this means is we can change our main query before it’s run

pre_get_posts

pre_get_posts fires for every post query:

— get_posts()— new WP_Query()— Sidebar widgets— Admin screen queries— Everything!

How do we use it?

function my_pre_get_posts( $query ) {

// Check if the main query and home and not admin

if ( $query->is_main_query() && is_home() && !is_admin() ) {

// Display only posts that belong to a certain Category

$query->set( 'category_name', 'fatuity' );

// Display only 3 posts per page

$query->set( 'posts_per_page', '3' );

return;

}

}

// Add our function to the pre_get_posts hook

add_action( 'pre_get_posts', 'my_pre_get_posts' );

In functions.php[example 1]

function my_pre_get_posts( $query ) {

// Check if the main query and home and not admin

if ( $query->is_main_query() && is_home() && !is_admin() ) {

// Display only posts that belong to a certain Category

$query->set( 'category_name', 'fatuity' );

// Display only 3 posts per page

$query->set( 'posts_per_page', '3' );

return;

}

}

// Add our function to the pre_get_posts hook

add_action( 'pre_get_posts', 'my_pre_get_posts' );

In functions.php[example 1]

function my_pre_get_posts( $query ) {

// Check if the main query and home and not admin

if ( $query->is_main_query() && is_home() && !is_admin() ) {

// Display only posts that belong to a certain Category

$query->set( 'category_name', 'fatuity' );

// Display only 3 posts per page

$query->set( 'posts_per_page', '3' );

return;

}

}

// Add our function to the pre_get_posts hook

add_action( 'pre_get_posts', 'my_pre_get_posts' );

In functions.php[example 1]

function my_pre_get_posts( $query ) {

// Check if the main query and home and not admin

if ( $query->is_main_query() && is_home() && !is_admin() ) {

// Display only posts that belong to a certain Category

$query->set( 'category_name', 'fatuity' );

// Display only 3 posts per page

$query->set( 'posts_per_page', '3' );

return;

}

}

// Add our function to the pre_get_posts hook

add_action( 'pre_get_posts', 'my_pre_get_posts' );

In functions.php[example 1]

In functions.php[example 1]function my_pre_get_posts( $query ) {

// Check if the main query and home and not admin

if ( $query->is_main_query() && is_home() && !is_admin() ) {

// Display only posts that belong to a certain Category

$query->set( 'category_name', 'fatuity' );

// Display only 3 posts per page

$query->set( 'posts_per_page', '3' );

return;

}

}

// Add our function to the pre_get_posts hook

add_action( 'pre_get_posts', 'my_pre_get_posts' );

In functions.php[example 2]function my_pre_get_posts( $query ) {

// Check if the main query and movie CPT archive and not admin

if($query->is_main_query() && is_post_type_archive('movie') && !is_admin()){

// Display only posts from a certain taxonomies

$query->set( 'tax_query', array( array( 'taxonomy' => 'genre', 'field' => 'slug', 'terms' => array ( 'fantasy', 'sci-fi' ) ) ) );

return; }

}

// Add our function to the pre_get_posts hook

add_action( 'pre_get_posts', 'my_pre_get_posts' );

In functions.php[example 2]function my_pre_get_posts( $query ) {

// Check if the main query and movie CPT archive and not admin

if($query->is_main_query() && is_post_type_archive('movie') && !is_admin()){

// Display only posts from a certain taxonomies

$query->set( 'tax_query', array( array( 'taxonomy' => 'genre', 'field' => 'slug', 'terms' => array ( 'fantasy', 'sci-fi' ) ) ) );

return; }

}

// Add our function to the pre_get_posts hook

add_action( 'pre_get_posts', 'my_pre_get_posts' );

In functions.php[example 2]function my_pre_get_posts( $query ) {

// Check if the main query and movie CPT archive and not admin

if($query->is_main_query() && is_post_type_archive('movie') && !is_admin()){

// Display only posts from a certain taxonomies

$query->set( 'tax_query', array( array( 'taxonomy' => 'genre', 'field' => 'slug', 'terms' => array ( 'fantasy', 'sci-fi' ) ) ) );

return; }

}

// Add our function to the pre_get_posts hook

add_action( 'pre_get_posts', 'my_pre_get_posts' );

In functions.php[example 2]function my_pre_get_posts( $query ) {

// Check if the main query and movie CPT archive and not admin

if($query->is_main_query() && is_post_type_archive('movie') && !is_admin()){

// Display only posts from a certain taxonomies

$query->set( 'tax_query', array( array( 'taxonomy' => 'genre', 'field' => 'slug', 'terms' => array ( 'fantasy', 'sci-fi' ) ) ) );

return; }

}

// Add our function to the pre_get_posts hook

add_action( 'pre_get_posts', 'my_pre_get_posts' );

Remember...

Do:— Use pre_get_posts— Check if it’s the main query by using is_main_query()— Check it’s not an admin query by using is_admin()— Check for specific templates using is_home(), etc..— Set up your query using same parameters as WP_Query()

Don’t:— Use query_posts()unless you have a very good reason AND you use wp_reset_query()

( if you really need a secondary query, use new WP_Query() )

References

// You Don’t Know Query - Andrew Nacinhttp://wordpress.tv/2012/06/15/andrew-nacin-wp_query

http://www.slideshare.net/andrewnacin/you-dont-know-query-wordcamp-portland-2011

// Make sense of WP Query functionshttp://bit.ly/wpsequery

// Querying Posts Without query_postshttp://developer.wordpress.com/2012/05/14/querying-posts-without-query_posts

// pre_get_posts on the WordPress Codexhttp://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts

// Example code on Githubhttps://github.com/maddisondesigns/wpmelb-nov

That’s all folks!☺

Thanks! Questions?

top related