Похожие записи в WordPress без плагина: вывод и кеш
← Блог
WordPress · 03.10.2026 · 4 мин чтения

Похожие записи в WordPress без плагина: вывод и кеш

Блок похожих записей предлагает читателю другие статьи по теме. В WordPress его можно собрать без плагина: найти записи с общими рубриками или метками и вывести ссылки после текста статьи.

Сначала напишем запрос через WP_Query, затем добавим кеширование и вывод в single.php. Примеры рассчитаны на классическую тему.

1. Поиск похожих записей по рубрикам

Функция возвращает массив ID записей из тех же рубрик, без текущей. Добавь в functions.php:

function mytheme_get_related_post_ids( $post_id, $count = 3 ) {
    $categories = wp_get_post_categories( $post_id );
    if ( ! $categories ) {
        return array();
    }

    $query = new WP_Query( array(
        'post_type'           => 'post',
        'post_status'         => 'publish',
        'category__in'        => $categories,
        'post__not_in'        => array( $post_id ),
        'posts_per_page'      => $count,
        'ignore_sticky_posts' => true,
        'no_found_rows'       => true,
        'fields'              => 'ids',
    ) );

    return $query->posts;
}

Параметры, которые часто забывают:

  • ignore_sticky_posts — отключает приоритет закреплённых записей. Он не исключает их из результата: запись всё ещё может попасть в список, если подходит под условия запроса.
  • no_found_rows — WordPress не будет считать общее число найденных записей. Для блока без пагинации этот подсчёт не нужен.
  • fields => 'ids' — запрос вернёт только ID, их удобно кешировать.

Сортировка по умолчанию — от новых к старым. 'orderby' => 'rand' лучше не использовать: на большой базе ORDER BY RAND() заметно медленнее, а с кешем случайность всё равно пропадёт.

Как выбирать записи по меткам

Метки подходят, если они точнее описывают тему статьи, чем рубрики. В первой функции замени wp_get_post_categories() на wp_get_post_tags(), проверку ! $categories — на ! $tags, а category__in — на tag__in. Фрагмент замены:

$tags = wp_get_post_tags( $post_id, array( 'fields' => 'ids' ) );
// ...
'tag__in' => $tags,

2. Кеширование списка через Transients API

Чтобы не выполнять один и тот же запрос при каждом просмотре, сохрани массив ID через Transients API. Срок хранения в примере — не больше суток:

function mytheme_get_related_posts_cached( $post_id, $count = 3 ) {
    $key = 'mytheme_related_' . $post_id . '_' . $count;
    $ids = get_transient( $key );

    if ( false === $ids ) {
        $ids = mytheme_get_related_post_ids( $post_id, $count );
        set_transient( $key, $ids, DAY_IN_SECONDS );
    }

    return $ids;
}

Пустой массив тоже сохраняется в кеше. Значение false означает, что кеш отсутствует или уже истёк; WordPress может удалить transient и раньше указанного срока.

После новой публикации список пересчитается при первом запросе без действующего кеша. Для немедленного обновления нужно очистить связанные ключи при сохранении записи, например на хуке save_post. Учитывай все затронутые списки, а не только кеш изменённой статьи.

3. Вывод похожих статей в single.php

Вставь в single.php после контента записи:

<?php
$related_ids = mytheme_get_related_posts_cached( get_the_ID() );

if ( $related_ids ) : ?>
    <section class="related" aria-labelledby="related-title">
        <h2 id="related-title">Похожие статьи</h2>
        <ul class="related__list">
            <?php foreach ( $related_ids as $related_id ) : ?>
                <li class="related__item">
                    <a href="<?php echo esc_url( get_permalink( $related_id ) ); ?>">
                        <?php echo esc_html( get_the_title( $related_id ) ); ?>
                    </a>
                </li>
            <?php endforeach; ?>
        </ul>
    </section>
<?php endif; ?>

Функции получают ID явно, поэтому глобальная $post не меняется и не нужен wp_reset_postdata(). Если в карточке нужна картинка, добавь get_the_post_thumbnail( $related_id, 'card' ) — размеры и вывод миниатюр разобраны в статье о миниатюрах записей.

Если похожих записей не хватает

В маленьком блоге в рубрике может быть одна-две записи. Дополни список свежими записями из любых рубрик:

$ids = mytheme_get_related_post_ids( $post_id, $count );

if ( count( $ids ) < $count ) {
    $extra = get_posts( array(
        'post__not_in'        => array_merge( array( $post_id ), $ids ),
        'posts_per_page'      => $count - count( $ids ),
        'ignore_sticky_posts' => true,
        'fields'              => 'ids',
    ) );
    $ids = array_merge( $ids, $extra );
}

Внутри условия if ( false === $ids ) замени строку $ids = mytheme_get_related_post_ids( $post_id, $count ); этим фрагментом. Вызов set_transient() оставь после него: в кеш должен попасть дополненный список.

Свежие записи из других рубрик могут быть не связаны с темой. Если используешь такое дополнение, назови блок «Читайте также».

Документация

Есть вопрос или дополнение?

Обсудить в Telegram

Добавить комментарий