Count posts that have specific taxonomy term attached

Public API for the rescue

category is a Taxonomy that’s already built in. Therefore it’s quite easy to get its term count with get_terms( $tax, array( /* args */ ) );

$terms = get_terms( 'category', array(
    'fields' => 'count',
) );

This will do a pretty fast COUNT (*) query so you don’t have to worry about performance.

Alternate solution

You could as well just do a normal call to get_terms() and then alter the selects with the filter:

// The core filter:
apply_filters( 'get_terms_fields', $selects, $args )

// Example callback:
add_action( 'get_terms_fields', 'wpse105174_get_terms_fields_cb', 10, 2 );
function wpse105174_get_terms_fields_cb( $selects, $args )
{
    return array( 't.term_id', 'COUNT(*)' );
}

…where $selects is aan array (which will be imploded to a comma separated string).

Making it even faster

You could then further modify the query and restrict it to only some specific categories (terms/taxons) with a WHERE t.slug = whatever

// The core filter:
apply_filters( 'terms_clauses', compact( $pieces ), $taxonomies, $args );

// Example callback:
add_action( 'terms_clauses', 'wpse105174_terms_clauses_cb', 10, 3 );
function wpse105174_terms_clauses_cb( $pieces, $taxonomies, $args )
{
    $pieces['where'] = " WHERE t.slug = whatever";
    // Or do some `str_replace`, `preg_replace`, whatever fits in here

    return $pieces;
}

You could set the $pieces['join'] = ''; as well if you don’t need access to the term_taxonomy-table.

Cache it

Finally you could utilize the Transients API to save your results (as serialized array) to the DB, so you don’t have to query the count every time you need it.

Leave a Comment