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!

Are your smart devices spying on you? Make better purchasing choices and find products that respect your privacy at

RSS Latest posts from my personal blog

Most viewed posts

Subscribe to RSS feed

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

Stanislav KhromovStanislav Khromov

Download the slides


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) {

    $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()) :


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:



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

    $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()


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.
Twitter Profile
Visit my other blog

Comments 2