Как использовать pre_get_posts для изменения запросов WordPress без плагинов

Диагностика проблемы: когда нужно изменять стандартные запросы WordPress

Часто возникает задача изменить выборку записей на страницах блога, архивов или в виджетах без создания отдельного плагина или кастомного запроса. Например, убрать записи определённой категории с главной, изменить число постов на странице или добавить фильтрацию по метаполям. Для этого WordPress предлагает хук pre_get_posts, который позволяет вмешиваться в основной запрос до его выполнения.

Как работает хук pre_get_posts

pre_get_posts — это фильтр, который срабатывает перед выполнением запроса WP_Query. С помощью него можно модифицировать SQL-запрос, изменяя параметры выборки записей. Он срабатывает как для главного запроса (is_main_query()), так и для дополнительных.

Важно: чтобы не повлиять на административную панель и избежать конфликтов, всегда проверяйте контекст выполнения.

Пример: убрать категорию с главной страницы

function exclude_category_from_home( $query ) {
    if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) {
        // ID категории, которую нужно исключить
        $query->set( 'cat', '-5' );
    }
}
add_action( 'pre_get_posts', 'exclude_category_from_home' );

В этом коде мы исключаем категорию с ID 5 из главной страницы блога. Минус перед ID означает исключение.

Пошаговое решение: изменение запроса для кастомных условий

Рассмотрим, как изменить число постов на странице архива и добавить фильтр по произвольному полю (meta_key).

  1. Определите условие страницы в запросе (например, архив категории).
  2. Проверьте, что это главный запрос, а не админка.
  3. Используйте методы $query->set() для изменения параметров.
function modify_archive_query( $query ) {
    if ( ! is_admin() && $query->is_main_query() && $query->is_category() ) {
        // Устанавливаем 10 записей на страницу
        $query->set( 'posts_per_page', 10 );

        // Фильтруем по метаполю 'featured' со значением 'yes'
        $query->set( 'meta_key', 'featured' );
        $query->set( 'meta_value', 'yes' );
    }
}
add_action( 'pre_get_posts', 'modify_archive_query' );

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

Чтобы убедиться, что изменения сработали:

  • Откройте страницу, для которой меняли запрос (главная, архив).
  • Проверьте, что записи соответствуют новым параметрам (например, отсутствует категория, изменено число постов).
  • Включите режим отладки и выведите SQL-запрос: echo $wp_query->request; в файле шаблона.
  • Используйте плагины типа Query Monitor для наглядного анализа запросов.

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

  • Изменение запроса в админке: отсутствие проверки ! is_admin() вызовет баги в панели управления. Исправьте добавлением проверки.
  • Изменение не главного запроса: без is_main_query() вы можете изменить сторонний запрос (например, виджета), что приведёт к ошибкам.
  • Неверное использование параметров: например, установка cat через положительное число добавит только эту категорию, а не исключит. Используйте минус для исключения.
  • Неочевидный конфликт с другими плагинами: если другие хуки тоже меняют запрос, проверьте приоритет добавления функций и используйте remove_action.

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

  • Не нагружайте запросы сложными мета-запросами без необходимости: они сильно влияют на скорость. Используйте индексы в базе или кэширование.
  • Минимизируйте изменения в pre_get_posts: пишите точные условия, чтобы не ломать другие части сайта.
  • Тестируйте на staging-сервере: любое изменение запросов может привести к появлению пустых страниц или циклов.

Сравнение способов изменения запросов: плагин vs. pre_get_posts vs. WP_Query

Способ Плюсы Минусы
pre_get_posts Изменяет главный запрос без создания нового; гибко; не требует плагинов Нужно внимательно писать условия; можно сломать другие запросы
WP_Query (с кастомным запросом) Полный контроль над выборкой; можно использовать в шаблонах Создаёт дополнительный запрос; может ухудшать производительность
Плагины для фильтрации контента Удобно для новичков; готовые решения Могут быть избыточными; нагрузка на сайт; риск конфликтов
Как избежать проблем с перенаправлением в WordPress: практические решения и примеры кода
23.03.2026
Как удалить и заблокировать загрузочные файлы в WordPress
26.03.2026
Решение проблемы нерабочих AJAX-запросов WooCommerce после обновления
14.06.2026
Как удалить или изменить заголовок страницы в WordPress через фильтр
08.02.2026
Как использовать хук woocommerce_order_status_changed для автоматизации в WooCommerce
27.05.2026