Exclude Subcategories in a Loop

This code snippet excludes the subcategories in a loop. Just insert the code in your functions.php of your theme or in a Plugin and you are done.

if ( !function_exists('fb_filter_child_cats') ) {
	function fb_filter_child_cats( $cats ) { 
		global $wp_query, $wpdb;
	
		if ( is_category() ) {
			
			// get children ID's
			if ( $excludes = get_categories( "child_of=" . $wp_query->get('cat') ) ) {
				
				// set array with ID's
				foreach ( $excludes as $key => $value ) {
					$exclude[] = $value->cat_ID;
				}
			}
			
			// remove child cats
			if ( isset($exclude) && is_array($exclude) ) {
				$cats .= " AND " . $wpdb->prefix . "term_taxonomy.term_id NOT IN (" . implode(",", $exclude) . ") ";
			}
		}
		
		return $cats;
	}
	
	if ( !is_admin() ) {
		add_filter( 'posts_where', 'fb_filter_child_cats' );
	}
}

Update for WP 3.1 and higher:

if ( !function_exists('fb_filter_child_cats') ) {
	function fb_filter_child_cats( $cats ) {
		global $wp_query, $wpdb;
		if ( is_category() ) {
			// get children ID's
			if ( $excludes = get_categories( "child_of=" . $wp_query->get('cat') ) ) {
				// set array with ID's
				foreach ( $excludes as $key => $value ) {
					$exclude[] = $value->cat_ID;
				}
			}
			// remove child cats
			if ( isset($exclude) && is_array($exclude) ) {
				$cats .= " AND " . $wpdb->prefix . "term_relationships.term_taxonomy_id NOT IN (" . implode(",", $exclude) . ") ";
			}
		}
		return $cats;
	}
	if ( !is_admin() ) {
		add_filter( 'posts_where', 'fb_filter_child_cats' );
	}
}

and also Update 3 for a better solution without an sql-select:

function fb_filter_child_cats($query) {
	
	$cat = get_term_by('name', $query->query_vars['category_name'], 'category');
	$child_cats = (array) get_term_children( &$cat->term_id, 'category' );
	// also possible
	// $child_cats = (array) get_term_children( get_cat_id($query->query_vars['category_name']), 'category' );
	
	if ( !$query->is_admin )
		$query->set( 'category__not_in', array_merge($child_cats) );
	
	return $query;
}
add_filter( 'pre_get_posts', 'fb_filter_child_cats' );

Comments are closed.

22 comments

  1. Robert

    Frank,

    it seems that you changed the excluded categories' array name midway. I'd suggest to amend line #18 to read:

    $cats .= " AND " . $wpdb->prefix . "term_taxonomy.term_id NOT IN (" . implode(",", $exclude) . ") ";
    

    NB: implode(",", $exclude) replaces implode(",", $exs)

  2. Frank

    @Robert: thanks for your hint, i have fix the bug

  3. Cristian

    First of all, thanks for this function!

    I've added the script in my ../themes/my_theme/functions.php and this is the error:

    Catchable fatal error: Object of class stdClass could not be converted to string in line:
    $cats .=" AND ".$wpdb->prefix ."term_taxonomy.term_id NOT IN (".implode(",", $excludes).")";

    What could it be?

  4. Michael

    Cristian:
    Should be
    $cats .=" AND ".$wpdb->prefix ."term_taxonomy.term_id NOT IN (".implode(",", $exclude).")";

  5. michael

    Is there a way to do this on the homepage?

  6. amir

    Hi,
    I need a little help regarding tweaking the display of Categories on Navigation Bar..
    I have a parent Category (let's suppose A)
    then sub categories under this Parent Category let's suppose A1, A2, A3, A4, A5, A6..
    Now I want to add sub categories under these Child Categories, I mean, now I want to add some sub categories under A1, A2, A3, A4 but I dont want to show them in navigation bar..
    2nd, I want if someone clicks at A,,,,it shouls not display all posts under A but it should just diplay its sub categories & same if someone clicks on A1 or A2, it should not display Posts of A1 or A2 rather it should diplay sub categories of A1 ,, A2 & so on..
    is it possible ??
    Thanks

  7. Metapony

    That's an interesting solution, but it's actually much easier than this.

    See http://tomcat23.wordpress.com/2010/07/26/query_posts-and-how-to-use-it-in-your-functions-php-template-file/

  8. Wolf Larsen

    Is there a way to exclude not all subcategories, just 2 out of 5?
    Thank you,
    Wolf

  9. Jan

    It seems that this is not working with WP 3.1
    (do you think it can be related to changing deprecated "caller_get_posts" with "ignore_sticky_posts"?).
    Can you please fix or update the code?
    With the new version 3.1 of WordPress, it gives the next error:

    WordPress database error: [Unknown column 'wp_term_taxonomy.term_id' in 'where clause']
    SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (21,45,49) ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish') AND wp_term_taxonomy.term_id NOT IN (42,46) GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 3

    in the front page (don't display the posts of the featured categories), and don't list any post in the categories-list pages.

    Thanks

  10. Wolf Larsen

    Yes, this code doesnt work with 3.1. WordPress didnt find any articles in the category.

    Wolf

  11. Michael

    I agree. This doesnt seem to work with WP 3.1. Hm... Any ideas how to fix it?

  12. Frank

    Now, i have update for WP 3.1

  13. Martin

    Thank you, Frank, but I can not see any change in the code update for WP 3.1 ...

  14. Frank

    @Martin: sorry, i have an error with my copy/paste workflow :(
    Now i have change the code and hope, this works

  15. Jan

    Thank you for your interest and your attention, but I agree with Martin, the updated code is the same as the previous one.
    Maybe a little lapse...

    Sorry for my bad english in this and my previous reply (I'm writing from Spain).

    I really appreciate all the advices of your site.

  16. Jan

    Sorry, I had not refreshed this page in my browser...
    I see now the changes.
    Seems very interesting, I will check and try it.
    Once again many thanks, thanks also for your site, and sorry for my poor english.

  17. Michael

    Thanks for fixing it, Frank! ;-)

5 pingbacks

  1. Daily Tip: Hack the WordPress Loop to Exclude Subcategories - WordPress MU and BuddyPress plugins, themes, support, tips and how to's
  2. be infected
  3. Artikel aus Unterkategorien ausblenden | perun.net
  4. WordPress: Artikel aus Unterkategorien ausblenden | perun.net
  5. Artikel von Unterkategorien in Hauptkategorien ausblenden | michael-fitzen.de