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

Диагностика: почему стандартные запросы не подходят для сложной фильтрации

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

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

Пошаговое решение: корректное применение pre_get_posts

1. Определяем, где нужно изменить запрос

Чтобы избежать влияния на админ-панель и другие запросы, обязательно проверяем параметры запроса:

function my_custom_filter( $query ) {
    // Проверяем, что это основной запрос и не админка
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }
    
    // Пример: изменить запрос только на главной странице
    if ( $query->is_home() ) {
        // Добавляем условие фильтрации
    }
}
add_action( 'pre_get_posts', 'my_custom_filter' );

2. Добавляем условия фильтрации

Например, исключим из главной страницы записи из категории с ID 5 и добавим мета-запрос, чтобы выводить только опубликованные товары с метаполем in_stock равным 1.

function my_custom_filter( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    if ( $query->is_home() ) {
        // Исключаем категорию с ID 5
        $query->set( 'cat', '-5' );

        // Добавляем мета-запрос
        $meta_query = array(
            array(
                'key' => 'in_stock',
                'value' => '1',
                'compare' => '=',
            ),
        );
        $query->set( 'meta_query', $meta_query );
    }
}
add_action( 'pre_get_posts', 'my_custom_filter' );

3. Обработка кастомных типов записей и таксономий

Если нужно фильтровать архив кастомного типа записей или таксономии, проверяем соответствующие условные теги и меняем параметры:

function my_custom_post_type_filter( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    if ( $query->is_post_type_archive( 'product' ) ) {
        // Выводим только опубликованные товары с ценой больше 1000
        $meta_query = array(
            array(
                'key' => 'price',
                'value' => 1000,
                'compare' => '>',
                'type' => 'NUMERIC',
            ),
        );
        $query->set( 'meta_query', $meta_query );
    }
}
add_action( 'pre_get_posts', 'my_custom_post_type_filter' );

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

  • Очистите кеш сайта и браузера, чтобы изменения запроса вступили в силу.
  • Откройте фронтенд страницы, где вы изменяли запрос (например, главную или архив кастомного типа).
  • Проверьте, что записи отфильтрованы согласно заданным условиям (например, отсутствуют записи из исключённой категории или отображаются товары с метаполем in_stock = 1).
  • Для детальной отладки можно временно добавить вывод SQL-запроса:
add_action( 'pre_get_posts', function( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }
    // Ваша логика

    add_filter( 'posts_request', function( $sql ) {
        error_log( $sql ); // Запишет запрос в error_log
        return $sql;
    } );
} );

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

  • Изменение запросов в админке: забыли проверить is_admin(), из-за чего ломаются запросы в административной панели. Решение: всегда добавляйте проверку if ( is_admin() ) return;.
  • Не проверяется основной запрос: изменения применяются ко всем WP_Query, включая вложенные запросы (например, в виджетах). Решение: используйте $query->is_main_query() для попадания только в главный запрос.
  • Неправильный синтаксис мета-запросов: не указываете тип данных или используете неправильный ключ. Решение: всегда задавайте type в мета-запросах, особенно для чисел.

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

  • Не используйте pre_get_posts для сложных выборок с большими мета-запросами без индексации — это сильно нагружает базу данных.
  • При необходимости кэшируйте результаты запросов с помощью Transients API или плагинов кеширования.
  • Избегайте дублирования логики фильтрации в шаблонах и хуках — централизуйте её в pre_get_posts.

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

МетодПлюсыМинусы
Использование pre_get_postsГибкая фильтрация, применяется до выполнения запроса, не требует кастомных запросов в шаблонахТребует аккуратности, можно сломать админку без проверок
Создание кастомного WP_Query в шаблонеЛокальный контроль над выборкой, меньше риска повлиять на другие части сайтаДублирование кода, хуже поддерживаемость
Использование плагинов фильтрацииУпрощение для неразработчиков, готовые интерфейсыМожет быть перегружено, меньше гибкости, влияет на производительность
Как создать собственный плагин для автоматизации задач в WordPress
28.03.2026
Как создать собственный тип записей в WordPress с примерами кода
30.11.2025
Обновление WordPress без потери настроек и данных
07.01.2026
Как добавить поле в форму регистрации WordPress
26.11.2025
Как добавить поддержку WebP в WordPress: практическое руководство
14.04.2026