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
22 responses to “Exclude Subcategories in a Loop”
Frank,
it seems that you changed the excluded categories’ array name midway. I’d suggest to amend line #18 to read:
NB:
implode(",", $exclude)
replacesimplode(",", $exs)
@Robert: thanks for your hint, i have fix the bug
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?
Cristian:
Should be
$cats .=" AND ".$wpdb->prefix ."term_taxonomy.term_id NOT IN (".implode(",", $exclude).")";
Is there a way to do this on the homepage?
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
[…] 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 […]
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/
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 …
[…] WP Engeneer Diesen Artikel […]
[…] WP Engeneer Diesen Artikel […]
[…] 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 […]
Is there a way to exclude not all subcategories, just 2 out of 5?
Thank you,
Wolf
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
Yes, this code doesnt work with 3.1. WordPress didnt find any articles in the category.
Wolf
I agree. This doesnt seem to work with WP 3.1. Hm… Any ideas how to fix it?
Now, i have update for WP 3.1
Thank you, Frank, but I can not see any change in the code update for WP 3.1 …
@Martin: sorry, i have an error with my copy/paste workflow 🙁
Now i have change the code and hope, this works
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.
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.
Thanks for fixing it, Frank! 😉