The function you are using are scrambled and does not make much sense. Also, it is very static in that you cannot return a count according to custom parameters like post type, post status, or custom field. Another thing to note, if a post belongs to a term and one of its child terms, the post will be counted twice, so you will end up with a post count which is more than what you actually have.
IMHO, I will just make use of a custom query to make the function dynamic and to return a true count instead of a bloated one due to posts belonging to a parent and a child term.
THE IDEA
The tax_query
has a parameter called include_children
, which by default is set to true
. This parameter will include all child terms of the terms passed to the terms
parameter, so it will return posts from the passed terms and all of it's children.
Secondly, we only need to query one post to get a post count. What WP_Query
does by default is, it will continue to search the db for matching posts, even though it has already found the required posts matching the query. This is done in order to calculate pagination, and a count of all these posts matching the query is stored in the $found_posts
property of the query object.
To save on db calls and time spend doing it, we will also just query the ID
post field and not the complete WP_Post
object.
THE CODE
First of all, a few notes
I will comment the code as I go along so you can follow and understand what will be happening
/**
* Function to get post count from given term or terms and its/their children
*
* @param (string) $taxonomy
* @param (int|array|string) $term Single integer value, or array of integers or "all"
* @param (array) $args Array of arguments to pass to WP_Query
* @return $q->found_posts
*
*/
function get_term_post_count( $taxonomy = 'category', $term = '', $args = [] )
{
// Lets first validate and sanitize our parameters, on failure, just return false
if ( !$term )
return false;
if ( $term !== 'all' ) {
if ( !is_array( $term ) ) {
$term = filter_var( $term, FILTER_VALIDATE_INT );
} else {
$term = filter_var_array( $term, FILTER_VALIDATE_INT );
}
}
if ( $taxonomy !== 'category' ) {
$taxonomy = filter_var( $taxonomy, FILTER_SANITIZE_STRING );
if ( !taxonomy_exists( $taxonomy ) )
return false;
}
if ( $args ) {
if ( !is_array )
return false;
}
// Now that we have come this far, lets continue and wrap it up
// Set our default args
$defaults = [
'posts_per_page' => 1,
'fields' => 'ids'
];
if ( $term !== 'all' ) {
$defaults['tax_query'] = [
[
'taxonomy' => $taxonomy,
'terms' => $term
]
];
}
$combined_args = wp_parse_args( $args, $defaults );
$q = new WP_Query( $combined_args );
// Return the post count
return $q->found_posts;
}
USAGE
You can use the function in the following ways
CASE 1
Single term (term ID 21
) with default category taxonomy
$count = get_term_post_count( 'category', 21 );
echo $count;
CASE 2
Array of term ids with custom taxonomy my_taxonomy
$count = get_term_post_count( 'my_taxonomy', [21, 41, 52] );
echo $count;
CASE 3
Single term from default category taxonomy from custom post type cpt
and post status trash
$args = [
'post_type' => 'cpt',
'post_status' => 'trash'
];
$count = get_term_post_count( 'category', 21, $args );
echo $count;
USAGE 4
If you need to get a post count from all terms of a given taxonomy, simply set the $term
parameter to all
$count = get_term_post_count( 'category', 'all' );
echo $count;