Каким образом можно подсчитать количество публикаций для каждой таксономии в WordPress?

Привет! <br/> У меня есть задача: нужно определить общее количество постов для каждой таксономии в WordPress. <br/> Ниже приведен пример кода: <br/> <br/> <pre><code class="php">public static function output_html(int $post_id, array $post_types) : string {
   $all_tax = Taxonomy::get_taxonomies($post_types);
   if($all_tax) {
      foreach( $all_tax as $tax_name =&gt; $label ) {   
         $terms = self::get_terms($tax_name);
           if($terms) {
             foreach ($terms as $term_id =&gt; $name) {
                 self::updateCounts($tax_name, $term_id);
                     echo '&lt;div class="term-item" &gt;'. esc_html($name) .'&lt;/div&gt;';
                     // code...
               }
           }
      }
   }
}
// Количество постов для каждого термина считается в этом методе
private static function updateCounts(string $taxName, int $termId) : void {
     $post_types = (array) get_taxonomy($taxName)-&gt;object_type;
     //$guid = sha1(json_encode([$termId, $taxName, $post_types]));
     //if (get_transient($guid) === false) {
     foreach ($post_types as $type) {
	$args = [  'posts_per_page' =&gt; -1,
			'post_type' =&gt; $type,
			'tax_query' =&gt; [['taxonomy' =&gt; $taxName, 'terms' =&gt; $termId]],
		     ];
		     $countQuery = new \WP_Query($args);
		      update_term_meta($termId, "count_{$type}", $countQuery-&gt;found_posts);
	}
      //set_transient($guid, true, 60);
    }
}</code></pre> <br/> <br/> В этом коде создается множество запросов, поскольку на каждый термин осуществляется отдельный WP_Query для подсчета количества постов, и результаты записываются в таблицу "wp_termmeta". Это вызывает значительную нагрузку на сервер. <br/> Например, если у нас будет 40 терминов, каждый из которых связан с разными типами постов (2...
  • 22 апреля 2025 г. 18:25
Ответы на вопрос 2
Ваш код действительно генерирует множество запросов к базе данных, что может сильно нагружать сервер, особенно при большом количестве терминов и постов. Вместо того чтобы делать отдельный запрос для каждого термина, мы можем оптимизировать процесс и выполнить один запрос, который подсчитает количество постов для всех терминов в данной таксономии одновременно.

Вот предложенный вариант кода, который использует `get_posts` с `tax_query`, чтобы избежать множества запросов:

```php
public static function output_html(int $post_id, array $post_types): string {
    $all_tax = Taxonomy::get_taxonomies($post_types);
    if ($all_tax) {
        foreach ($all_tax as $tax_name => $label) {
            $terms = self::get_terms($tax_name);
            if ($terms) {
                // Подсчитываем общее количество постов разом
                self::updateCounts($tax_name, $terms);
                
                foreach ($terms as $term_id => $name) {
                    echo '<div class="term-item">' . esc_html($name) . ' (' . esc_html(get_term_meta($term_id, "count_{$post_types[0]}", true)) . ')</div>';
                    // code...
                }
            }
        }
    }
}

private static function updateCounts(string $taxName, array $terms): void {
    $post_types = (array) get_taxonomy($taxName)->object_type;

    // Сначала создаем массив для результатов
    $results = array_fill_keys($terms, 0);

    foreach ($post_types as $type) {
        // Формируем запрос для получения постов, связанных с терминами
        $args = [
            'posts_per_page' => -1,
            'post_type' => $type,
            'tax_query' => [
                [
                    'taxonomy' => $taxName,
                    'terms' => array_keys($results),
                    'field' => 'term_id',
                ],
            ],
        ];
        
        $query = new \WP_Query($args);
        $posts = $query->get_posts();

        // Подсчитываем количество постов для каждого термина
        foreach ($posts as $post) {
            $terms_in_post = wp_get_post_terms($post->ID, $taxName);
            foreach ($terms_in_post as $term) {
                if (isset($results[$term->term_id])) {
                    $results[$term->term_id]++;
                }
            }
        }

        // Сохраняем результаты в wp_termmeta
        foreach ($results as $term_id => $count) {
            update_term_meta($term_id, "count_{$type}", $count);
        }
    }
}
```

### Объяснение кода:

1. **Запрос с `tax_query`:** Мы используем один запрос для получения всех постов, которые соответствуют всем терминам данной таксономии, вместо того чтобы отправлять отдельный запрос для каждого термина.

2. **Подсчет постов:** Как только мы получаем все посты, мы проходимся по ним и подсчитываем количество для каждого термина, который связан с постом.

3. **Обновление метаданных:** Наконец, как и раньше, мы обновляем соответствующие метаданные для каждого термина, но теперь это делается одиночным проходом через результат.

Этот подход значительно снижает нагрузку на базу данных и увеличивает эффективность подсчета.
Если к таксономии привязан один post_type, то для запроса достаточно аргумента count 

$args = array(
	'count' => true,
);

$terms = get_terms( $args );


Если же через стандартные аргументы задачу не решить, посмотрите кеширование через функцию wp_cache_set()

$cache_key = 'term_post_counts';
$counts = get_transient($cache_key);

if ($counts === false) {
    $counts = $wpdb->get_results($sql);
    set_transient($cache_key, $counts, HOUR_IN_SECONDS);
}
Похожие вопросы