Useful Snippets

Useful Snippets


This blog is used to collect useful snippets related to Linux, PHP, MySQL and more. Feel free to post comments with improvements or questions!

July 2020
M T W T F S S
 12345
6789101112
13141516171819
20212223242526
2728293031  

Categories


Andrew Nacin: WP_Query / WordPress In-depth – summary and highlights

Stanislav KhromovStanislav Khromov

Download the slides

Summary

This is a summary of the WP_Query WordPress In-depth talk by Andrew Nacin from WordCamp Netherlands 2012.

Main point: Do not use query_posts() in your themes or plugins

query_posts() is bad because it overwrites the main WordPress query, which resides in a global variable called $wp_query.

The proper way of modifying the main query is via the pre_get_posts hook.

Example that excludes posts from author with id = 5 from the front page main query.

function nacin_alter_home($query) {
    if($query->is_main_query() && $query->is_home())
        $query->set('author', '-5');
}
add_action('pre_get_posts', 'nacin_alter_home');

Example that excludes posts from author with id = 5 from a specific page template:

function nacin_alter_template($query) {
    if(!$query->is_main_query())
        return;
    if(!is_page_template('my-template.php'))
        return;

    $query->set('author', '-5');
}
add_action('pre_get_posts', 'nacin_alter_template');

These examples should be put in your themes functions.php or in a plugin.

The proper way of creating a secondary query / secondary loop in your plugin or theme is this:

$query = new WP_Query( ... );

while($query->have_posts()) :
    $query->the_post();
endwhile;

wp_reset_postdata();

wp_reset_postdata() is needed to clean the $post global, so that the any other loops (including the main loop) may use it.


Video notes

Below is additional information that may be of interest.

is_author(), is_single() and similar methods are just wrapper functions that run functions on the $wp_query object

Implementation of is_author() from WordPress core:

function is_author(){
    global $wp_query;
    return $wp_query->is_author();
}
If you decide to run query_posts() despite everything you have read above, you need to use wp_reset_query() afterwards.

Like so:

query_posts('author=-5');
while(have_posts()):
    the_post();
endwhile;

wp_reset_query();

Note:
wp_reset_query() automatically runs wp_reset_postdata()

WordPress keeps the real main query in a variable called $wp_the_query.

query_posts() implementation from WordPress core:

function query_posts($query) {
    //Break the reference to $wp_the_query
    unset($wp_query);

    $wp_query =& new WP_Query($query);
    return $wp_query;
}
WordPress knows which query you want before the theme is loaded.

It is suboptimal to run query_posts() inside your theme, since WordPress has already ran the query it thinks you need before the theme loaded.

Every time you run query_posts() or create a new WP_Query() (secondary loop), four queries are run:
  1. Getting the posts according to your query string
  2. Calculating how many posts exist for this query (to create pagination)
  3. Loading all metadata for the posts
  4. Loading all taxonomy term information for the posts

It is possible to turn off queries 2-4 to increase performance, like this:

$my_query = new WP_Query(array(
    'no_found_rows' => true,
    'update_post_meta_cache' => false,
    'update_post_term_cache' => false
));
Always check if you are modifying is_main_query() (and modify only it) when using the pre_get_posts hook

Otherwise sidebars and other loops might break.

Theme functions.php file loads before the rest of the theme

That’s why you can hook into pre_get_posts, which happens before the theme is loaded.

query_posts() and WP_Query diagram.

Below is a nice diagram that shows the flow of query_posts()

avoid_query_posts

Image source

Web Developer at Aftonbladet (Schibsted Media Group)
Any opinions on this blog are my own and do not reflect the views of my employer.
LinkedIn
Twitter
WordPress.org Profile
Visit my other blog

Comments 2