Как использовать хук pre_get_posts для фильтрации записей в WordPress

Что такое хук pre_get_posts и когда он нужен

Хук pre_get_posts позволяет изменять основной WP_Query ещё до запуска SQL-запроса. Это мощный инструмент для фильтрации и модификации списков записей (постов, товаров, кастомных типов) в любом месте сайта — на главной, архивных страницах, в админке или на фронтенде.

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

Диагностика: как понять, что нужен pre_get_posts

Если вы хотите:

  • изменить набор записей в стандартных лупах WordPress;
  • фильтровать архив категорий, тегов или кастомных таксономий;
  • исключить или включить записи по метаполям, авторам, статусу;
  • изменить порядок сортировки (orderby) для страниц блога или каталога WooCommerce;

то pre_get_posts — ваш выбор. Альтернативы вроде query_posts() или создания новых WP_Query не оптимальны и могут привести к ошибкам.

Пошаговое решение: пример фильтрации записей по метаполю

Предположим, нужно на странице архива постов вывести только те записи, у которых кастомное поле _my_custom_flag установлено в yes.

Добавьте следующий код в functions.php вашей темы или в плагин:

function filter_posts_by_custom_meta(\WP_Query $query) {
    // Проверяем, что это главный запрос и фронтенд
    if ( ! is_admin() && $query->is_main_query() && $query->is_archive() ) {
        $meta_query = array(
            array(
                'key' => '_my_custom_flag',
                'value' => 'yes',
                'compare' => '=',
            ),
        );
        $query->set('meta_query', $meta_query);
    }
}
add_action('pre_get_posts', 'filter_posts_by_custom_meta');

Объяснение:

  • is_main_query() гарантирует, что меняется только основной запрос страницы;
  • is_archive() ограничивает действие архивными страницами (можно заменить на is_home() для главной блога);
  • через set('meta_query', ...) добавляется фильтр по метаполю.

Пример фильтрации WooCommerce товаров по атрибуту

Чтобы показать на странице магазина только товары с атрибутом pa_color равным red, используйте:

function filter_woocommerce_products_by_color(\WP_Query $query) {
    if ( ! is_admin() && $query->is_main_query() && is_post_type_archive('product') ) {
        $tax_query = array(
            array(
                'taxonomy' => 'pa_color',
                'field' => 'slug',
                'terms' => 'red',
            ),
        );
        $query->set('tax_query', $tax_query);
    }
}
add_action('pre_get_posts', 'filter_woocommerce_products_by_color');

Как проверить, что фильтрация работает

  • Откройте соответствующую страницу (архив, магазин и т.п.)
  • Убедитесь, что выводятся только записи/товары с нужными параметрами;
  • Для отладки добавьте var_dump($query->request) внутри функции, чтобы увидеть сгенерированный SQL-запрос;
  • Используйте плагин Query Monitor для анализа запросов WP_Query.

Частые ошибки при работе с pre_get_posts

  • Не проверяете is_main_query() — меняется не только основной запрос, из-за чего страница может отобразиться некорректно.
  • Отсутствует условие is_admin() — изменение запросов в админке приводит к сбоям.
  • Неправильное использование условий типа is_archive(), is_home(), is_post_type_archive() — фильтр не сработает на нужной странице.
  • Перезаписываете существующий meta_query или tax_query без объединения, из-за чего теряются другие фильтры.

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

  • Не добавляйте тяжелые JOIN или сложные запросы в pre_get_posts без оптимизации — это замедлит загрузку страницы.
  • Используйте кеширование (например, Object Cache) для повторных запросов с фильтрами.
  • Для сложных условий объединяйте фильтры через $query->set('meta_query', array_merge($existing_meta_query, $new_meta_query)), чтобы не терять данные.
  • Тестируйте влияние фильтра на разные страницы сайта.

Сравнение вариантов фильтрации записей

МетодПлюсыМинусы
pre_get_postsИзменяет основной запрос без создания нового; оптимально для изменения архивов и главной;Требует аккуратности с условиями; может влиять на производительность при сложных запросах;
query_posts()Простой вызов для изменения запроса;Перезаписывает глобальный запрос, вызывает баги и проблемы с пагинацией;
WP_Query новый объектГибкий, не влияет на основной запрос;Нужно вручную выводить результаты и управлять пагинацией;
Как удалить или изменить slug кастомного типа записи в WordPress без потери данных
03.03.2026
Как добавить поддержку Gutenberg блоков в своем плагине WordPress
22.03.2026
Как правильно отключить Gutenberg для отдельных типов записей в WordPress
03.05.2026
Как создать настройку плагина в WordPress: подробное руководство для разработчиков
28.11.2025
Как использовать WP-Cron для задач на выполнение по расписанию в WordPress
16.05.2026