wpdebug.ru wordpress WP Debug

Как отладить дубли запросов и повторяющиеся записи в WordPress

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

Ниже — рабочая схема, которая помогает не гадать, а быстро локализовать источник проблемы и исправить его без лишних правок в теме.

Как выглядит проблема и где искать источник дублей

Сначала стоит разделить сценарии. Если запись повторяется в ленте блога, причина часто в запросе или фильтре. Если дубль виден только в отдельном блоке темы, проблема обычно в шаблоне. Если посты дублируются после подключения плагина фильтрации, надо смотреть, не создаёт ли он дополнительный запрос поверх основного.

Типичные признаки

  • одна и та же запись встречается дважды в home.php, archive.php или в блоке на главной;
  • в админке записи уникальны, а на фронтенде вывод повторяется;
  • дубли появляются только для части рубрик, таксономий или страниц пагинации;
  • после установки SEO- или фильтрующего плагина поведение меняется без правок темы.

Что проверить в первую очередь

  • не вызывается ли один и тот же цикл дважды;
  • не используется ли query_posts() вместо отдельного WP_Query;
  • нет ли фильтра pre_get_posts, который меняет основной запрос без условий;
  • не добавляет ли тема записи вручную через массив, а затем ещё раз через стандартный цикл.

Диагностика: как понять, где именно появляется дубль

Самый быстрый способ — посмотреть, что реально возвращает запрос. Для этого не нужно сразу лезть в базу. Достаточно временно вывести ID записей и сравнить их с тем, что видно на странице.

<?php
// Временно вставьте в шаблон архива или в нужный шаблонный файл.
if ( have_posts() ) {
    while ( have_posts() ) {
        the_post();
        echo '<p>ID: ' . get_the_ID() . ' — ' . esc_html( get_the_title() ) . '</p>';
    }
}
?>

Если ID уже повторяются в этом выводе, проблема в запросе. Если ID уникальны, а на странице всё равно виден дубль, значит запись выводится второй раз в другом месте шаблона — например, в сайдбаре, в хук-области темы или через блок.

Полезно также проверить, не вмешивается ли код в основной запрос. Для этого можно временно добавить логирование в pre_get_posts и посмотреть, какие условия срабатывают.

<?php
add_action( 'pre_get_posts', function( WP_Query $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    error_log( 'Main query: ' . print_r( $query->query_vars, true ) );
} );

Если в логах видно, что фильтр срабатывает на архиве, главной и пагинации одинаково, а условия не ограничены, это уже кандидат на исправление.

Пошаговое решение без ломки шаблона

1. Не используйте query_posts()

Это частая причина неожиданных дублей и поломки пагинации. query_posts() перезаписывает глобальный запрос и часто создаёт побочные эффекты. Если нужен отдельный список записей, используйте WP_Query.

<?php
$posts = new WP_Query( array(
    'post_type'      => 'post',
    'posts_per_page' => 6,
    'post__not_in'   => array( get_queried_object_id() ),
) );

if ( $posts->have_posts() ) {
    while ( $posts->have_posts() ) {
        $posts->the_post();
        the_title( '<h2>', '</h2>' );
    }
    wp_reset_postdata();
}

2. Ограничьте изменения основного запроса

Если вы меняете количество постов или исключаете рубрику через pre_get_posts, обязательно проверяйте контекст. Иначе фильтр начнёт работать там, где не должен: в админке, в поиске, на пагинации или в REST-запросах.

<?php
add_action( 'pre_get_posts', function( WP_Query $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    if ( $query->is_home() ) {
        $query->set( 'posts_per_page', 10 );
        $query->set( 'category__not_in', array( 12 ) );
    }
} );

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

3. Исключите повторный вывод в шаблоне

Иногда проблема не в запросе, а в том, что один и тот же блок подключён дважды: в шаблоне и через хук темы. Проверьте, не вызывается ли один и тот же partial в нескольких местах. Если блок должен появляться только один раз, вынесите его в отдельную функцию и подключайте централизованно.

<?php
function wpdebug_render_featured_posts() {
    $q = new WP_Query( array(
        'post_type'      => 'post',
        'posts_per_page' => 3,
        'no_found_rows'  => true,
    ) );

    if ( ! $q->have_posts() ) {
        return;
    }

    echo '<div class="featured-posts">';
    while ( $q->have_posts() ) {
        $q->the_post();
        echo '<article>' . esc_html( get_the_title() ) . '</article>';
    }
    echo '</div>';

    wp_reset_postdata();
}

Сравнение подходов: плагин, код или правка шаблона

ПодходКогда уместенМинус
Правка шаблонаДубли только в одной области темыНужно понимать структуру темы
Код через pre_get_postsНужно управлять основным запросомЛегко задеть лишние страницы без условий
Плагин для отладкиНужно быстро увидеть SQL и хукиДополнительная нагрузка и лишние зависимости

Если задача разовая, лучше сначала отладить кодом и логами. Плагин имеет смысл только как временный инструмент диагностики, а не как постоянное решение.

Проверка результата после исправления

После правки не ограничивайтесь визуальной проверкой главной страницы. Дубли часто всплывают только на пагинации, в рубриках или на мобильной версии темы.

  • откройте главную, архив рубрики и страницу пагинации;
  • сравните ID записей в HTML или через временный вывод;
  • проверьте, не сломалась ли пагинация после изменения запроса;
  • посмотрите error_log, если добавляли временное логирование;
  • убедитесь, что один и тот же пост не приходит из двух разных блоков.

Если используете кэш, очистите его после проверки. Иначе можно принять старый HTML за результат новой правки.

Частые ошибки и как их исправить

Фильтр срабатывает везде

Причина — нет проверки is_main_query() или контекста страницы. Исправление: ограничьте фильтр конкретным архивом, поиском или главной.

Пагинация показывает повторяющиеся записи

Часто это происходит после замены основного запроса через query_posts() или при неверной настройке offset. Если нужен сдвиг выборки, учитывайте пагинацию отдельно, а не просто добавляйте offset без расчёта.

Запись выводится дважды из-за шаблона

Проверьте, не подключён ли один и тот же partial через get_template_part() в двух местах, а также не дублируется ли блок через хук темы.

Дубль появляется только после плагина

Отключите плагин и проверьте, остаётся ли проблема. Если исчезает, ищите его фильтры запросов, виджеты или блоки, которые он добавляет в контент.

Практические советы по безопасности и производительности

Отладку лучше делать на staging-копии или хотя бы с временным логированием, которое потом удаляется. Не оставляйте error_log в боевом коде без необходимости. Для запросов, которые не требуют подсчёта общего числа записей, используйте 'no_found_rows' => true — это уменьшает лишнюю нагрузку на базу.

Если вы работаете с крупным сайтом, полезно держать под рукой инструменты для чистки дублей и технической оптимизации. В некоторых случаях быстрее сначала убрать лишние SEO-дубли и мусорные шаблонные элементы, а уже потом править запросы. Для этого может пригодиться Clearfy Pro: https://wpshop.ru/plugins/clearfy.

Но даже с плагином логика остаётся той же: сначала локализовать источник дубля, потом убрать причину, затем проверить результат на реальных шаблонах и страницах пагинации.

×

AI-плагин от WPShop.ru

анализирует конкурентов

пишет статьи

готовит SEO

генерирует изображения

и еще кое-что...
WPGPT
Плагин, который наполняет ваш сайт WordPress
Узнать больше