Отображать ссылку на архив таксономии только в том случае, если в нем есть записи с определенными пользовательскими значениями полей


Сообщения на моем сайте описывают будущие события, с датой события, записанной в пользовательском поле во времени Unix.

Как правило, только предстоящие события имеют отношение к посетителям. Таким образом, я хотел бы отображать навигационные ссылки на архив таксономии только в том случае, если в таксономии есть хотя бы одно предстоящее событие (дата события > сегодняшняя дата).

Есть ли более разумный способ, чем следующий?

<?php
$terms = get_terms( array(
    'taxonomy' => 'genre',
    'hide_empty' => true,
) );

$today = time() - 86400;

foreach($terms as $term) {
    $query = new WP_Query( array( 'meta_key' => 'event_date', 'meta_value' => $today, meta_compare => '>=', 'tax_query' => array( array( 'taxonomy' => 'genre', 'field' => 'term_id', 'terms' => $term->term_id, ), ), ) );
    if (($query->found_posts) > 1) {
    echo '<li><a href="/genre/' . $term->slug . '">' . $term->name . '</a></li>';
    }
} ?>

Это работает, как и ожидалось, но добавляет около 100 запросов к каждой загружаемой странице, которая это немного тревожит.

Author: thedorklord, 2019-04-22

1 answers

Есть два решения, которые немного умнее, о которых я могу подумать...

1. Не извлекайте все

Вам не нужна вся информация об этих сообщениях. Все, что вам нужно, - это граф, так что... Вам не нужно заполнять все поля для этих сообщений, и вам не нужно заполнять их все...

"Более разумный" способ оптимизации этого кода - запрашивать только идентификаторы записей, соответствующих вашему запросу, и ограничивать запрос только одним результатом...

<?php
$terms = get_terms( array(
    'taxonomy' => 'genre',
    'hide_empty' => true,
) );

$today = time() - 86400;

foreach ($terms as $term) {
    $query = new WP_Query( array(
        'meta_key' => 'event_date',
        'meta_value' => $today,
        'meta_compare' => '>=', 
        'tax_query' => array( 
            array( 'taxonomy' => 'genre', 'field' => 'term_id', 'terms' => $term->term_id ),
        ),
        'posts_per_page' => 1,
        'fields' => 'ids'
    ) );
    if ( $query->found_posts > 0 ) {
        echo '<li><a href="/genre/' . $term->slug . '">' . $term->name . '</a></li>';
    }
}
?>

2. И если это не так достаточно оптимизирован...

Вы всегда можете написать пользовательский SQL-запрос, который будет получать только соответствующие термины... Но это всегда рискованный способ, потому что такие запросы будут обходить фильтры... Поэтому, если есть фильтр, скрывающий термин или некоторые сообщения, ваш пользовательский запрос проигнорирует его.

PS.

Это не лучший способ напечатать ссылку на термин:

<a href="/genre/' . $term->slug . '">

Вы должны использовать get_term_link вместо этого:

<a href="'. esc_attr( get_term_link( $term ) ) .'">
 0
Author: Krzysiek Dróżdż, 2019-04-22 20:18:29