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

Posted

in

by

Comments

22 responses to “Exclude Subcategories in a Loop”

  1. Robert Avatar

    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 Avatar

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

  3. Cristian Avatar

    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 Avatar

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

  5. michael Avatar
    michael

    Is there a way to do this on the homepage?

  6. amir Avatar

    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. […] only parent categories, then you’ll need a little bit of help. I found this function over at WPengineer.com. Simply drop it into your theme’s functions.php file and your loop will automatically exclude […]

  8. Artikel von Unterkategorien in Hauptkategorien ausblenden…

    Leider etwas lang der Titel, aber anders konnte ich es gerade nicht beschreiben . Für gewöhnlich werden in WordPress Artikel von Unterkategorien in den Hauptkategorien eingeblendet. Dies kann je nach Projekt etwas verwirrend, ja sogar nervig …

  9. […] etwas verwirrend, ja sogar nervig sein. Genau vor diesem Problem stand auch ich gerade, bis ich diesen kleinen Code für die functions.php bei wpengineer.com gefunden habe. Dieser bezweckt, dass die Hauptkategorien […]

  10. Wolf Larsen Avatar
    Wolf Larsen

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

  11. Jan Avatar
    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

  12. Wolf Larsen Avatar
    Wolf Larsen

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

    Wolf

  13. Michael Avatar

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

  14. Frank Avatar

    Now, i have update for WP 3.1

  15. Martin Avatar
    Martin

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

  16. Frank Avatar

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

  17. Jan Avatar

    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.

  18. Jan Avatar

    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.

  19. Michael Avatar

    Thanks for fixing it, Frank! 😉