Как использовать хук 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 в шаблонеЛокальный контроль над выборкой, меньше риска повлиять на другие части сайтаДублирование кода, хуже поддерживаемость
Использование плагинов фильтрацииУпрощение для неразработчиков, готовые интерфейсыМожет быть перегружено, меньше гибкости, влияет на производительность
Создание динамических QR-кодов в WordPress с помощью PHP
27.12.2025
Как удалить старые мета-поля в WordPress при удалении записи
21.02.2026
Как создать собственный виджет в WordPress с примером кода
17.11.2025
Как использовать настройки пересылки электронной почты в WordPress
13.01.2026
Как создать эффективный кеш в WordPress с помощью перегрузки функций
22.11.2025