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;

4 Answers 4


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);
  • Upvote to Helga as she mentioned pre_get_posts first. Commented Sep 4, 2014 at 5:33
  • 1
    instead of 'category__not_in' or 'category__in', you could use 'cat' and use a string as value e.g. '2,-4'. this way, not only the specified category would be included/excluded, but also its children.
    – honk31
    Commented Jun 6, 2019 at 14:01
  • 1
    You, ma'am, have committed a horrible crime. You should be ashamed of yourself! Function name "wpa_44672"? Really? :P
    – Ares
    Commented Apr 25, 2020 at 21:42
  • Are you really trolling on a post from 8 years to make fun of the fact that I used a unique function name with almost 0% chance of conflicting with anything? Commented Apr 27, 2020 at 14:18

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.


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

  • 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
    Commented Mar 6, 2012 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
    Commented Mar 6, 2012 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
    Commented Mar 7, 2012 at 0:05

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');  ?>

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.