I have a basic archives.php file. I was trying to get it to display only posts from category 1. When I do query_posts('cat=1'), the URL is then ignored and all posts in category 1 are displayed.

For example, lets say I have one post in category 1: it's called "testing post" and is dated November, 1, 2012. Lets say I have another post in category 5 dated April 2, 2012.

With the current archives.php (using the query posts for cat 1) the URL: http://testing.com/2012/04 resolves to show all posts within category 1. No good, since the post is dated November, and the URL is querying for April (04).

The archives.php will resolve http://testing.com/2012/04 and http://testing.com/2012/11 as each of those months have a post in them (albeit not from category 1), it will not however resolve http://testing.com/2012/09 as that month doesn't have any posts (category 1 or otherwise)

How can I make the archives.php file query for the current month (whatever is in the URL) but only display posts in category 1? Asked another way, how can I make http://testing.com/2012/04 come up with a "sorry there are no posts here" message, like in http://testing.com/2012/09 while http://testing.com/2012/11 still displays the one post from category 1?

1 Answer 1


First: don't use query_posts(), ever.

Second, to create a category archive index page template for a specific category, refer to the Codex entry for the Template Hierarchy:

  • category-{slug}.php
  • category-{id}.php
  • category.php
  • archive.php
  • index.php

So, if you have a category, 'foobar', with a category ID of 1, you could do either of the following:

  • category-foobar.php
  • category-1.php

And WordPress will use that template to render the archive index page for that category.

The reason your query is getting stomped has nothing to do with your template file, however; it is because you're completely overriding the default query, by using query_posts().

To filter your date-based archives by a specific category, use pre_get_posts instead:

function wpse75668_filter_pre_get_posts( $query ) {
    // Only modify the main loop query
    // on the front end
    if ( $query->is_main_query() && ! is_admin() ) {
        // Only modify date-based archives
        if ( is_date() ) {
            // Only display posts from category ID 1
            $query->set( 'cat', '1' );
add_action( 'pre_get_posts', 'wpse75668_filter_pre_get_posts' );

For more information, see Nacin's WordCamp presentation, You Don't Know Query.

  • okay. for all you folks wondering why I marked this as correct... it was because of the pre_get_posts (can't believe I didn't think of that!) the other stuff, however, isn't applicable. using those templates will do exactly what you think it will but a template called category-1.php won't do anything for a URL ending with /2012/04 (this is why we needed to use pre_get_posts) secondly, it's tough to say don't use query_posts ever. It's super easy syntax, and on sites without tons of traffic it seems to not make any difference. furthermore, it's easier to read than some buried function. Dec 11, 2012 at 2:54
  • The main reason for the template information is because I misread the question on the first read. I could edit the question and remove it? That said: calling query_posts() may be easier to read in the template file, but - especially the way you were using it - it is absolutely, 100% _doing_it_wrong(), and is why you were not getting the query output as you wanted it. Dec 11, 2012 at 3:10
  • right, but just because it's wrong in that example doesn't mean it's ALWAYS wrong. I knew it was wrong there... Dec 11, 2012 at 16:27
  • 1
    No, I'd say pretty definitively that it is always wrong to use query_posts(). There is never a scenario in which filtering pre_get_posts or instantiating a new WP_Query() object isn't the preferred method. Dec 11, 2012 at 16:33

Your Answer

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

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