I'm building a site with several post types and am using a single index.php to query the archive for each one in turn. One of these post types is hierarchical and I'd like to just query the parent. I can use query_posts to limit to 'post_parent' => 0 but that creates a new query and resets the post type argument meaning that I'd have to create separate queries for each post type.

Is there a way to limit while ( have_posts() ) : the_post(); to parents only without creating a new query?

  • 3
    Have you looked into the pre_get_posts hook? It can help you modify the main query.
    – birgire
    Dec 9, 2014 at 11:43
  • 1
    You shouldn't be using query_posts, if you ever need to query for posts, use WP_Query instead, or at the very least, get_posts. If you ever need to modify what posts appear on a page or archive, always use pre_get_posts. query_posts exists because its removal would break a lot of websites.
    – Tom J Nowell
    Dec 9, 2014 at 12:30

1 Answer 1


In your functions.php you can create a function that will hook into the pre_get_posts hook. Something like (just an example):

function alter_query($query){
  $query->set('post_parent', 0);
add_action( 'pre_get_posts', 'alter_query' );

There you can alter the main query. That way while(have_posts()) : the_post(); will still just normally work. (You should check if you are altering the right query and such. Otherwise the post_parent will be applied to all query's by wordpress. You don't want that).

The BIG advantage is, that if you alter the main query, you only have to do that. Wordpress will still select the appriopiate template and such. If you also want to alter the template loaded, you can use the template_redirect hook.

  • 1
    Just a note, you should not be using template_redirect to load another template, the correct hook to use is template_include Dec 9, 2014 at 12:39
  • Spot on, thanks Sleuteltje for the clarification: I was trying to put this immediately before the loop but have now got it working perfectly from my functions.php. NB: I'm using the conditional: if ( !is_admin() && $query->is_main_query() && is_archive() ) Dec 9, 2014 at 12:44
  • Thank you Pieter Goosen :). You are right. I did know that somewhere in my brain, but must have forgotten. This explains a little trouble I was having not so long ago. So Thnx! :)
    – Sleuteltje
    Dec 9, 2014 at 12:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.