I have this code in my index.php file. I have a different template for a static home page, this is the blog page. I'm trying to exclude all posts with the category "new" which is tag_id "13"

<?php query_posts($query_string . '&cat=-13'); ?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

<a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"><p class='lead'><?php the_title(); ?></p></a>

<p><?php the_excerpt(); ?> <a href="<?php the_permalink()?>">read in full</a></p>

<p class='muted'><small>Written by: <?php the_author_posts_link(); ?><br>               
            <?php the_time('F jS, Y') ?></small></p><hr>

<?php endwhile; ?>

Any ideas why this isnt working?


3 Answers 3


Don't use query_posts(). Use pre_get_posts instead:

function wpse82745_filter_pre_get_posts( $query ) {
    // Only modify the main loop,
    // and only in the blog posts index
    if ( is_home() && $query->is_main_query() ) {
        $query->set( 'category__not_in', array( '13' ) );
add_action( 'pre_get_post', 'wpse82745_filter_pre_get_posts' );

This callback will exclude category 13 from the main loop in the blog posts index.


The $query_string is probably not initialized or not declared as global variable. Try adding

<?php global $query_string; ?>

before your code

  • I just tried this but to no avail
    – matt
    Jan 23, 2013 at 11:51
  • what do you get if you add <?php echo '$query_string='.$query_string.'<br>';?> below that line? Jan 23, 2013 at 12:18
  • I get $query_string=pagename=articles Articles being what we're calling the blog page
    – matt
    Jan 23, 2013 at 12:50
  • to add to that: i've added <?php global $query_string; ?> <?php echo '$query_string='.$query_string.'<br>';?> <?php $query_string = $query_string . '&cat=-13'; ?> <?php query_posts($query_string); ?> <?php echo '$query_string='.$query_string.'<br>';?> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> The output is: $query_string=pagename=articles $query_string=pagename=articles&cat=-13
    – matt
    Jan 23, 2013 at 12:55
  • however it still includes category of ID 13
    – matt
    Jan 23, 2013 at 12:58

I was running into the exact same mysterious issue, but struggling to solve it. I tried all of the suggestions in the comments here but nothing seemed to work.

In the end, since the key was retaining the pagination (as this was on the main blog section of the site and I wanted to exclude 'Other News'), I tried this:

//  Exclude the Other News category

$otherNews = get_category_by_slug('other-news'); 
$excludeID = $otherNews->term_id;

//query_posts($query_string . '&cat=-' . $excludeID);   <-- Doesn't work for some reason

$args = array('cat' => '-' . $excludeID, 'paged' => $paged );
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

...and this seemed to work perfectly.

  • see pre_get_posts in codex for how to correctly exclude categories from a query without wasting resources by running new queries in the template.
    – Milo
    May 30, 2013 at 18:42
  • @Milo As I mentioned, this solution didn't initially work as expected for me; however it seems this was because I was amending work done by a previous developer whose approach to queries across the theme seemed to be... haphazard at best. After updating some erroneous code, pre_get_posts worked perfectly. I suppose it begs the question 'When should I use query_posts()?', to which the answer appears to be 'Basically never'.
    – indextwo
    May 31, 2013 at 16:09

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.