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