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

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

Что такое хук pre_get_posts и зачем он нужен в WordPress

Хук pre_get_posts срабатывает в момент, когда WordPress формирует объект WP_Query, но ещё не выполняет SQL-запрос к базе. Это значит, что мы можем изменить параметры запроса, например, добавить условия для выборки постов, исключить определённые категории, изменить порядок сортировки или добавить мета-запросы.

Важный момент — этот хук вызывается для всех запросов, включая главный запрос (main query) и дополнительные (secondary queries). Поэтому при работе с ним нужно чётко проверять, с каким именно запросом мы имеем дело, чтобы не влиять на ненужные участки сайта.

Именно через pre_get_posts можно реализовать гибкие решения без создания собственных WP_Query, что улучшает производительность и упрощает поддержку кода.

Основы использования pre_get_posts: фильтрация главного запроса

Самый распространённый кейс — изменить главный запрос на странице блога, архива или главной. Например, ограничить вывод постов определённой категорией или изменить количество выводимых записей.

Пример функции, которая ограничивает главную страницу только постами из категории с ID 5:

function wpbono_pre_get_posts_main_query( $query ) {
    if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) {
        // Выводим только посты из категории с ID 5
        $query->set( 'cat', 5 );
        // Устанавливаем количество постов на странице
        $query->set( 'posts_per_page', 10 );
    }
}
add_action( 'pre_get_posts', 'wpbono_pre_get_posts_main_query' );

Такая простая функция позволяет гибко управлять основным запросом без создания отдельного шаблона.

Проверка условий запроса

В примере выше используется несколько условий:

  • ! is_admin() — чтобы действие не срабатывало в административной панели;
  • $query->is_main_query() — чтобы менять только главный запрос;
  • $query->is_home() — чтобы ограничить изменение только на главной странице блога.

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

Фильтрация архивов и кастомных типов записей через pre_get_posts

Еще один частый сценарий — изменить логику вывода на страницах архивов, например, для кастомных типов записей (Custom Post Types, CPT) или таксономий.

Допустим, у вас есть CPT portfolio, и вы хотите на архивной странице этого типа записей показывать только опубликованные элементы с определённой меткой.

function wpbono_pre_get_posts_portfolio( $query ) {
    if ( ! is_admin() && $query->is_main_query() && is_post_type_archive( 'portfolio' ) ) {
        // Показываем только опубликованные записи
        $query->set( 'post_status', 'publish' );
        // Добавим мета-запрос по ключу 'featured' = 'yes'
        $meta_query = array(
            array(
                'key' => 'featured',
                'value' => 'yes',
                'compare' => '=',
            ),
        );
        $query->set( 'meta_query', $meta_query );
        // Сортируем по дате публикации, сначала новые
        $query->set( 'orderby', 'date' );
        $query->set( 'order', 'DESC' );
    }
}
add_action( 'pre_get_posts', 'wpbono_pre_get_posts_portfolio' );

Такой подход позволяет централизованно управлять выводом данных без изменения шаблонов.

Работа с таксономиями внутри pre_get_posts

Если нужно фильтровать посты по таксономии, например, показывать только записи с определённым тегом или категорией, это делается через параметр tax_query. Пример ограничения архива записей типа post категорией «Новости»:

function wpbono_pre_get_posts_news_category( $query ) {
    if ( ! is_admin() && $query->is_main_query() && is_post_type_archive( 'post' ) ) {
        $tax_query = array(
            array(
                'taxonomy' => 'category',
                'field' => 'slug',
                'terms' => 'novosti',
            ),
        );
        $query->set( 'tax_query', $tax_query );
    }
}
add_action( 'pre_get_posts', 'wpbono_pre_get_posts_news_category' );

Обратите внимание, что tax_query — это массив условий, которые объединяются по умолчанию через «AND».

Изменение запросов пагинации и AJAX-запросов через pre_get_posts

Иногда нужно подстроить запрос под пагинацию или под AJAX-запросы, например, в кастомных фильтрах или лайтбоксах.

Для этого важно учитывать параметры запроса, такие как paged — номер страницы пагинации. Вот пример, как настраивать пагинацию для кастомного запроса:

function wpbono_pre_get_posts_pagination( $query ) {
    if ( ! is_admin() && $query->is_main_query() && is_archive() ) {
        $paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
        $query->set( 'posts_per_page', 8 );
        $query->set( 'paged', $paged );
    }
}
add_action( 'pre_get_posts', 'wpbono_pre_get_posts_pagination' );

Для AJAX-запросов, которые используют WP_Query, часто можно добавить дополнительный параметр запроса и при его наличии дополнять pre_get_posts нужной логикой. Например:

function wpbono_pre_get_posts_ajax_filter( $query ) {
    if ( ! is_admin() && isset( $_GET['ajax_filter'] ) && $query->is_main_query() ) {
        $query->set( 'meta_key', 'custom_field' );
        $query->set( 'orderby', 'meta_value_num' );
        $query->set( 'order', 'ASC' );
    }
}
add_action( 'pre_get_posts', 'wpbono_pre_get_posts_ajax_filter' );

Практические советы по работе с pre_get_posts и популярные ошибки

При работе с pre_get_posts важно помнить несколько правил, которые помогут избежать проблем и конфликтов:

  • Точно проверяйте условия запроса. Используйте is_admin(), is_main_query(), is_home(), is_archive() и другие условные теги, чтобы не затронуть лишние запросы.
  • Не создавайте бесконечные циклы. Внутри pre_get_posts не запускайте новые WP_Query, чтобы не вызвать рекурсию.
  • Используйте параметры запроса, а не фильтры. Меняйте параметры запроса через $query->set(), а не напрямую изменяйте SQL.
  • Тестируйте на разных страницах и сценариях. Разные шаблоны могут иметь свои особенности, поэтому важно проверять, что изменения не ломают логику сайта.

Если вы используете тему Bono от WPSHOP, то в ней уже предусмотрены корректные шаблоны для главного запроса, и pre_get_posts можно использовать для внесения изменений без правки шаблонов.

Заключение. Почему стоит использовать pre_get_posts в своих проектах

Хук pre_get_posts — это мощный и гибкий инструмент, который позволяет тонко настраивать вывод постов и кастомных типов записей в WordPress. Он помогает избежать дублирования запросов, упрощает поддержку кода и улучшает производительность сайта за счёт использования встроенных возможностей ядра.

Освоив pre_get_posts, вы сможете решать широкий спектр задач от фильтрации архивов до динамической сортировки и настройки пагинации. Это важный навык для любого разработчика, работающего с WordPress.

Использование хука before_add_to_cart в WooCommerce для проверки товара перед добавлением в корзину
19.04.2026
Как добавить динамические параметры в URL WordPress для фильтрации контента
15.02.2026
Как добавить удалённый вызов в WPBono Telegram Bot
12.01.2026
Как добавить Custom Post Type в WordPress: подробное руководство с примерами
24.11.2025
Как автоматически удалять неактивных пользователей в WordPress
07.04.2026