WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have this code for the loop, and I need to exclude a category 4 from this loop. Any suggestions on how to achieve this?

Code that starts the loop

 <?php if(have_posts()): ?>

    <ol class="item_lists">

        $end = array(3,6,9,12,15,18,21,24,27,30,33,36,39,42,45);
        $i = 0;

        while (have_posts()) : the_post();
           global $post;
share|improve this question
up vote 9 down vote accepted

you could use wp_parse_args() to merge your arguments into the default query

// Define the default query args
global $wp_query;
$defaults = $wp_query->query_vars;

// Your custom args
$args = array('cat'=>-4);

// merge the default with your custom args
$args = wp_parse_args( $args, $defaults );

// query posts based on merged arguments

although, i think the more elegant route is using the pre_get_posts() action. this modifies the query before the query is made so that the query isn't run twice.

check out:


based on that example to exclude category 4 from the index i'd put this in your functions.php:

add_action('pre_get_posts', 'wpa_44672' );

function wpa_44672( $wp_query ) {

    //$wp_query is passed by reference.  we don't need to return anything. whatever changes made inside this function will automatically effect the global variable

    $excluded = array(4);  //made it an array in case you  need to exclude more than one

    // only exclude on the home page
    if( is_home() ) {
        set_query_var('category__not_in', $excluded);
        //which is merely the more elegant way to write:
        //$wp_query->set('category__not_in', $excluded);
share|improve this answer
Upvote to Helga as she mentioned pre_get_posts first. – Brad Dalton Sep 4 '14 at 5:33

Adam is right. In addition, for pagination to work, you need to have something more like so:

<?php query_posts('post_type=post&paged='.$paged.'&cat=-4');  ?>
share|improve this answer

From your functions file

function remove_home_category( $query ) {
    if ( $query->is_home() && $query->is_main_query() ) {
        $query->set( 'cat', '-4' );
add_action( 'pre_get_posts', 'remove_home_category' );

This code alters the query before the actual query is run so is the most efficient hook to modify the loop in this case.

share|improve this answer
And why would you do that :-) – Pieter Goosen Sep 3 '14 at 15:59
Might be wrong but exclude from home loop? – Brad Dalton Sep 3 '14 at 19:17
Was actually hinting on you dumping code without proper explanation :-) – Pieter Goosen Sep 4 '14 at 4:23
Fair enough. Updated my answer and thanks for the reminder @goose! – Brad Dalton Sep 4 '14 at 5:31

Before the line

<?php if(have_posts()): ?>

Insert something like this

<?php query_posts($query_string . '&cat=-4'); ?>

This excludes the category with Category ID 4. As seen here

share|improve this answer
it does in fact remove the posts from that category but it's a kind of a portfolio on the users page, and now the pagination is broken on page 3. – jimilesku Mar 6 '12 at 23:50
I also have this custom made in the theme_setup.php: $newrules["user/({$author->nicename})/(portfolio)/?$"] = 'index.php?author_name=$matches[1]&baction=$matches[2]'; $newrules["user/({$author->nicename})/(portfolio)/page/?([0-9]+)/?$"] = 'index.php?author_name=$matches[1]&baction=$matches[2]&paged=$matches[3]'; – jimilesku Mar 6 '12 at 23:51
the pagination appears, and I can click it, but the page 2 ahs the same posts as page 1, and page 3 shows 404 error? Pls help :) – jimilesku Mar 7 '12 at 0:05

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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