In the previous post, I talked a bit about using `pre_get_posts` and how to efficiently exclude categories from the main loop.

Of course, in posts like that, the code is meant to be a point of reference or a starting place for which more advanced functionality can be written.

But one thing that I failed to mention about using `pre_get_posts` in WordPress is that it’s not limited to the public facing side of the site.

Using pre_get_posts in WordPress

As mentioned in the previous post, whenever you hook a function into the `pre_get_posts` action, then you’re passed – by reference – the `$wp_query` object. As such, the code looks something like this:

function demo_exclude_category( $wp_query ) {

    // Add the category to an array of excluded categories. In this case, though,
    // it's really just one.
    $excluded = array( '-1' );

    // Note that this is a cleaner way to write: $wp_query->set('category__not_in', $excluded);
    set_query_var( 'category__not_in', $excluded );

}
add_action( 'pre_get_posts', 'demo_exclude_category' );

The thing about this particular function is that it will exclude posts from that category in every single place `$wp_query` is used.

This means that the results will be excluded from places such as:

  • The RSS Feed
  • Archive Pages
  • Search Results
  • The Dashboard
  • …and so on

To that end, you’re likely only going to want to exclude it from certain places. So say, for example, that you wanted to exclude categories except from the search pages, the archives pages, and the admin dashboard.

Then the code would look something like this:

function demo_exclude_category( $wp_query ) {

    if ( ! is_admin() && ! is_search() && ! is_archive() ) {

        // Add the category to an array of excluded categories. In this case, though, it's really just one.
        $excluded = array( '-1' );

        // Note that this is a cleaner way to write: $wp_query->set('category__not_in', $excluded);
        set_query_var( 'category__not_in', $excluded );

    } // end if

}
add_action( 'pre_get_posts', 'demo_exclude_category' );

And for those of you who are more particular about conditionals, you could also write it to be `if ( ! ( is_admin() || is_search() || is_archive() ) )`, but that’s neither here nor there, really, for this post.

I just figure it’d come up in the comments at some point :).

Anyway, if you’re interested in the conditionals that WordPress offers, be sure to check out the Codex article on Conditional Tags as they come in handy when working with things like manipulating the main query.