WordPress分类文章总数计算并非那么简洁,很多时候,我们需要满足以下条件:
1、如果该分类存在子分类或多层级子分类,应将该分类及其下所有层级子分类中的文章全部计算在内。
2、如果该分类没有子分类,则计算该分类中的文章总数。
SQL 版本
public function get_tax_posts_count_with_children($term, $taxonomy) {
// 确保 $term 是有效的术语对象
if (is_numeric($term)) {
$term = get_term($term, $taxonomy);
}
if (is_wp_error($term) || !$term) {
return 0;
}
// 获取所有子分类ID(包括子孙分类)
$child_terms = get_term_children($term->term_id, $taxonomy);
$term_ids = [];
// 添加当前分类ID
$term_ids[] = (int) $term->term_id;
// 添加所有有效的子分类ID
if (!is_wp_error($child_terms) && !empty($child_terms)) {
foreach ($child_terms as $child_term_id) {
$term_ids[] = (int) $child_term_id;
}
}
// 去重
$term_ids = array_unique($term_ids);
// 如果只有一个分类(没有子分类),直接查询该分类的文章数量
if (count($term_ids) === 1) {
return (int) $term->count;
}
// 多个分类时进行联表查询
global $wpdb;
$placeholders = implode(',', array_fill(0, count($term_ids), '%d'));
// 获取所有公开的文章类型
$post_types = get_post_types(array('public' => true));
$post_type_placeholders = implode(',', array_fill(0, count($post_types), '%s'));
// 合并所有参数
$params = array_merge($term_ids, $post_types, [$taxonomy]);
$query = $wpdb->prepare(
"SELECT COUNT(DISTINCT p.ID)
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
WHERE tt.term_id IN ($placeholders)
AND p.post_status = 'publish'
AND p.post_type IN ($post_type_placeholders)
AND tt.taxonomy = %s",
$params
);
$count = (int) $wpdb->get_var($query);
return $count;
}主要实现:
- 获取所有公开的文章类型:使用
get_post_types(array('public' => true))获取所有公开的文章类型 - 动态构建文章类型条件:使用
IN条件来包含所有公开的文章类型 - 参数处理:正确合并术语ID、文章类型和分类法参数
WP_Query 版本
如果您更喜欢使用 WordPress 原生函数,这里是一个使用 WP_Query 的版本:
public function get_tax_posts_count_with_children($term, $taxonomy) {
// 确保 $term 是有效的术语对象
if (is_numeric($term)) {
$term = get_term($term, $taxonomy);
}
if (is_wp_error($term) || !$term) {
return 0;
}
// 获取所有子分类ID(包括当前分类)
$child_terms = get_term_children($term->term_id, $taxonomy);
$term_ids = [(int) $term->term_id];
if (!is_wp_error($child_terms) && !empty($child_terms)) {
$term_ids = array_merge($term_ids, array_map('intval', $child_terms));
$term_ids = array_unique($term_ids);
// 使用 WP_Query 统计所有公开文章类型的文章数量
$query_args = [
'post_type' => get_post_types(array('public' => true)), // 所有公开文章类型
'post_status' => 'publish',
'fields' => 'ids',
'posts_per_page' => -1,
'tax_query' => [
[
'taxonomy' => $taxonomy,
'field' => 'term_id',
'terms' => $term_ids,
'operator' => 'IN',
]
]
];
$query = new WP_Query($query_args);
return (int) $query->found_posts;
}
// 没有子分类时直接返回当前分类计数
return (int) $term->count;
}两种方案的比较
- SQL 版本:性能更好,适合处理大量数据
- WP_Query 版本:更符合 WordPress 开发规范,更容易维护
两个版本都能正确统计所有公开文章类型(post, page, 以及任何自定义的公开文章类型)在指定分类及其子分类中的文章总数。
推荐使用 SQL 版本,因为它在处理大量分类和文章时性能更优。

