Category and children post count

I’ve a situation where I cannot get correct post count from category… and I’ve tried everything but customizing wp_list_categories with walker.

So I’ve category hierarchy:

Read More
cat1
 cat2 (total 8)
  cat3 (total 5)
  cat4 (total 3)

All posts are under cat2 and cat3-cat4. I’m displaying cat1 and want to show post count.

If I use following function:

function wp_get_postcount($id) {
  //return count of post in category child of ID 15
  $count = 0;
  $taxonomy = 'category';
  $args = array('child_of' => $id);
  $tax_terms = get_terms($taxonomy,$args);
  foreach ($tax_terms as $tax_term) {
    $count +=$tax_term->count;
  }
  return $count;
}

I get total count of 16. Which is double the real amount, obviously counting twice.

Before this I tried:

$children_cats = get_categories(array(
        'hide_empty'    => 0,
        'taxonomy'      => 'category',
));

And used foreach on array and echoing out count. But it would return 0, obviously because parent cat has no posts selected under it…

wp_list_categories actually displays correct value. But I wasn’t able to extend it with walked so I would get my complicated html:

<li>
                            <a class="subcatimg" href="<?php echo $cat_link; ?>"><?php if (function_exists('get_cat_icon_lite')) echo get_cat_icon_lite( $child->cat_ID );?><span><?php _e('Show All','medishop'); ?></span></a>
                            <h4><a href="<?php echo $cat_link; ?>"><?php echo $child->name; ?></a></h4>
                            <p><span><?php echo wp_get_postcount($child->cat_ID); ?></span> <?php _e('products in this category','medishop'); ?></p>
                        </li>

I’m really out of options. Any advice?

Related posts

Leave a Reply

7 comments

  1. Checking Daniel Llewellyn code and WordPress’ WP_Query reference, I realized that we need to pass an array of array within the tax_query parameter. Otherwise, it’d just return all post counts.

    Here is the little modified code:

    if ( ! function_exists( 'ipt_kb_total_cat_post_count' ) ) :
    
    /**
     * Simple function to get category post count including all subcategories
     *
     * @link http://wordpress.stackexchange.com/a/91551 Stackexchange
     * @param  int $cat_id Category ID
     * @return int         Total post count
     */
    function ipt_kb_total_cat_post_count( $cat_id ) {
        $q = new WP_Query( array(
            'nopaging' => true,
            'tax_query' => array(
                array(
                    'taxonomy' => 'category',
                    'field' => 'id',
                    'terms' => $cat_id,
                    'include_children' => true,
                ),
            ),
            'fields' => 'ids',
        ) );
        return $q->post_count;
    }
    
    endif;
    

    Hope it helps someone like me.

  2. I get total count of 16. Which is double the real amount, obviously
    counting twice.

    The count property will return the number of posts in that specific category. You are getting 16 because those posts have both cat3 or cat4 and the parent category (cat2) assigned to them, and you’re adding up the counts.

    Assuming you are using that function like wp_get_postcount($id_of_cat2), just return the count property:

    $term = get_term((int)$id, $taxonomy);
    
    if(!($term instanceof WP_Error))
      return (int)$term->count;
    
    // or show the error...
    return 0;
    

    (This is the same as $child->count in your code below)

    But if you’re trying to get the post count of all child categories of cat1, like wp_get_postcount($id_of_cat1), which according to that category hierarchy doesn’t have any posts assigned to it, then add up the counts from the 2nd level. Your function seems to do exactly that.

  3. try:

    function wp_get_postcount($id) {
      //return count of post in category child of ID 15
      $q = new WP_Query(array(
        'nopaging' => true,
        'tax_query' => array(
          'taxonomy' => 'category',
          'field' => 'id',
          'terms' => $id,
          'include_children' => true,
      )));
      return $q->post_count;
    }
    

    caveat: I’ve not tested this.

  4. This isn’t the perfect solution, but might work as a quick fix, depending on your needs.

    Unfortunately, the way wordpress does this math, I don’t think “child_of” is the way you want to go. However, you could just select cat1 as a category on the posts in question.

    First, edit posts in Categories 3 & 4 and change from this:

    cat1 []
      cat2 [x]
         cat3 [x]
         cat4 []
    

    to this:

    cat1 [x]
      cat2 [x]
         cat3 [x]
         cat4 []
    

    Then fix your code to just count the # of posts in cat1, rather than all of its children.

    I was having a related issue, and solved it this way. It’s not recommended in every situation because it will break if the user doesn’t select categories properly. However, used properly, and it will fix your count issue.

    Additionally – if all posts are children of cat1 by default, to help the user in this instance, you could change the default category to ‘cat1’ for all new posts.

    Settings > Writing.
    
  5. My understand is all the posts are assigned to third level category (i.e cat3 & and cat4) and to their immediate parent (i.e cat2). But the posts are not assigned to first level category (i.e cat1).

    Now you want to count posts based on the top/first level category, if my understanding is correct, can you please tell me what is wrong with using the code below?

    function wp_get_postcount($id) {
      //return count of post in category child of ID 15
      $count = 0;
      $taxonomy = 'category';
      $args = array('child_of' => $id);
      $tax_terms = get_terms($taxonomy,$args);
      foreach ($tax_terms as $tax_term) {
          if ($tax_term->parent == $id) {
                $count +=$tax_term->count;
          }
      }
      return $count;
    }
    
  6. For those that are retrieving their taxonomies through get_terms(), you can pass the argument 'pad_counts' => true to add the children count into the parents.

    For example :

    $my_taxonomy_terms = get_terms(
        ['my_taxonomy'],
        ['orderby' => 'count', 'hide_empty' => false, 'order' => 'DESC', 'pad_counts' => true]
    );
    /* Assuming you have at least one term, this will show you 
       the number of objects that use your most popular term. */
    echo $my_taxonomy_terms[0]->count; 
    

    Source: here