2

I have a post category structure like this:

  • news
  • news / conferences
  • news / newsletter

In Appearance > Menu, I have added 3 menu items.

One each for the categories News, Conferences, Newsletter.

However, the News page also displays posts from Conferences and Newsletter.

How do I exclude posts from subcategories from being displayed in the parent category's page?

Thanks

0

Okay, as of 2019 I had to use slightly modified code and it works with any taxonomy. Not only with standard category. I used it with my setup of woocommerce and wp, preventing products from nested categories being displayed in parent cat:

add_action('parse_tax_query', 'wpse_filter_child_cats'); 

function wpse_filter_child_cats( $query ) {
    if ( is_tax( 'product_cat' ) ) {

        $queried_object = get_queried_object();
        $child_cats     = (array) get_term_children( $queried_object->term_id, 'product_cat' );

        if ( ! $query->is_admin ) //exclude the posts in child categories
        {

            $query->tax_query->queries[] = [
                'taxonomy' => 'product_cat',
                'field'    => 'term_id',
                'terms'    => array_merge( $child_cats ),
                'operator' => 'NOT IN'
            ];
        }

    }

}
0

I wrote my own function in order to exclude subcategory posts from the loop, as I found the code above didn't work for me.

In my theme archive.php file, above the loop, I list the subcategories:

    <?php
       $current_cat = get_queried_object();

       $args = array( 'parent'=>$current_cat->term_id, 'child_of' => $current_cat->term_id, );
        $categories = get_categories( $args );
        foreach($categories as $category) { ?>

           <h2><?php echo $category->name ;?></h2>
           <p> etc....</p>
      <?php } ?>

In my functions.php file, I've added the following custom function using pre_get_posts:

add_action( 'pre_get_posts', 'main_query_without_subcategory_posts' );

function main_query_without_subcategory_posts( $query ) {

if ( ! is_admin() && $query->is_main_query() ) {
    // Not a query for an admin page.
    // It's the main query for a front end page of your site.

    if ( is_category() ) {

   //Get the current category
        $current_category = get_queried_object();
        //get the id of the current category
        $current_cat_id = $current_category->term_id;

        //find the children of current category
        $cat_args = array( 'parent'=>$current_category->term_id, 'child_of' => $current_category->term_id, );
        $subcategories = get_categories( $cat_args );

        //Get a list of subcategory ids, stick a minus sign in front
        $subcat_id = array();         
        foreach($subcategories as $subcategory) { 
            $subcat_id[] = " -". $subcategory->term_id; 
        }

        //join them together as a string with a comma seperator          
        $excludesubcatlist = join(',', $subcat_id);

       //If you have multiple parameters, use $query->set multiple times
        $query->set( 'posts_per_page', '10' );
        $query->set( 'cat', ''.$current_cat_id.','.$excludesubcatlist.'' );
      }
    }
  }

Then in the archive.php, below the subcategories, I've added the regular WordPress loop which is now being modified by the above function:

<?php  while (have_posts() ) : the_post(); ?>
     <h2><?php the_title();?></h2>
     <p> etc....</p>
 <?php endwhile;?>

Though the WordPress codex says that using "category__in" will exclude posts from subcategories, that didn't work for me and subcategory posts were still showing.

https://codex.wordpress.org/Class_Reference/WP_Query#Category_Parameters

https://developer.wordpress.org/reference/hooks/pre_get_posts/

0

Use category__in instead of cat in your query.

As you know already, cat will query a category and it's sub categories:

$category = get_category (get_query_var('cat'));
WP_Query( 'cat'=>$category, 'post_type' => 'post' );

However, when using category__in, you'll will not get results from the subcategory.

$category = get_category (get_query_var('cat'));
WP_Query( 'category__in'=>$category, 'post_type' => 'post' );

The documentation on querying based on categories is here.

  • Hi and welcome to WP.SE. Keep in mind that get_category() returns OBJECT, ARRAY_A, or ARRAY_N. Assigning it directly won't work. You will have to check the return value and either assign a value via it's assoc/numerical key or via the object property. Make sure to check for its existence before using it. – kaiser Jan 17 '15 at 12:41
0

That works well and prevents posts in child categories from showing up in the parent category listing. However, make sure and have a post in that parent category, or you'll get a not found error if someone clicks on the parent category menu item.

2

I rewrote the code from a post at WP Engineer:

function wpse_filter_child_cats( $query ) {

if ( $query->is_category ) {
    $queried_object = get_queried_object();
    $child_cats = (array) get_term_children( $queried_object->term_id, 'category' );

    if ( ! $query->is_admin )
        //exclude the posts in child categories
        $query->set( 'category__not_in', array_merge( $child_cats ) );
    }

    return $query;
}
add_filter( 'pre_get_posts', 'wpse_filter_child_cats' );

Give it a try by pasting the snippet in your functions.php. Please keep in mind that a post can't belong to both parent category and child category, or you won't get it displayed.

  • Hi @1fixdotio. Thanks for helping out. I added this to my child theme's functions.php, but the subcategory posts still display in the parent category. – Steve Mar 3 '14 at 13:07
  • Did you get any error messages? May I know did you enable the permalink? – 1fixdotio Mar 3 '14 at 14:34
  • @Steve I've tested the code and it could work on my server. Just updated the code a bit, hope that helps. – 1fixdotio Mar 3 '14 at 14:53
  • No errors. I've uploaded the updated code and it is still not working. My theme is a child theme of Twenty Twelve. See this page which contains "2012 WA Men’s Shed Conference Presentations" & "The Warbler – WA Men’s Shed newsletter". These two are not in the parent category. – Steve Mar 4 '14 at 11:33
  • @Steve I created a child theme for twentytwelve and paste my code in functions.php, it worked well. Could you disable the plugins like jetpack and try again? – 1fixdotio Mar 4 '14 at 14:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.