wpwebsite.ru wordpress WPWebSite

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

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

Хук pre_get_posts позволяет изменить параметры основного запроса WordPress перед его выполнением. Это ключевой инструмент для тонкой настройки выборки постов, категорий, товаров WooCommerce и других типов записей без создания новых запросов.

Когда использовать pre_get_posts

  • Изменить количество постов на главной странице или в архиве;
  • Фильтровать товары WooCommerce по метаполям или атрибутам;
  • Исключить определённые категории из ленты;
  • Добавить кастомные параметры к запросу без изменения шаблонов.

Диагностика проблем с pre_get_posts

Частая ошибка — неправильно определить, какой запрос изменять. Основной запрос и дополнительные WP_Query обрабатываются одинаково через этот хук. Если изменить не тот запрос, результат не будет соответствовать ожиданиям или страница сломается.

Чтобы проверить, какой запрос обрабатывается, используйте условные теги и метод is_main_query(). Пример диагностики:

add_action('pre_get_posts', function($query) {
    if ($query->is_main_query()) {
        error_log('Основной запрос на странице: ' . (is_home() ? 'Главная' : 'Другая'));
    }
});

Если нет нужного результата, значит вы меняете не основной запрос.

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

Задача: показать на архиве товаров только те продукты, у которых метаполе _custom_label содержит значение new-arrival.

1. Подключаем хук pre_get_posts в functions.php или в плагине:

add_action('pre_get_posts', 'filter_woocommerce_products_by_custom_meta');
function filter_woocommerce_products_by_custom_meta($query) {
    // Проверить, что это фронтенд, архив товаров и основной запрос
    if (!is_admin() && $query->is_main_query() && is_post_type_archive('product')) {
        $meta_query = array(
            array(
                'key' => '_custom_label',
                'value' => 'new-arrival',
                'compare' => '='
            )
        );
        $query->set('meta_query', $meta_query);
    }
}

2. Очистить кэш сайта и браузера.

3. Обновить страницу архива товаров.

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

Самый простой способ — добавить в запрос дополнительное условие, которое меняет количество товаров. Например, добавьте в meta_query условие, которое убирает все товары:

$query->set('posts_per_page', 1);

Если на сайте отображается ровно один товар, значит ваш фильтр применяется. Также можно посмотреть SQL-запросы через плагин Query Monitor или вставить в код:

add_action('pre_get_posts', function($query) {
    if (!is_admin() && $query->is_main_query() && is_post_type_archive('product')) {
        error_log($query->request); // Покажет SQL-запрос в логе
    }
});

Частые ошибки при использовании pre_get_posts

  • Изменение не основного запроса: не использовать $query->is_main_query() ведёт к неожиданным результатам на странице.
  • Отсутствие проверки фронтенда: изменение запросов в админке может привести к ошибкам.
  • Перезапись meta_query без объединения: если в запрос уже есть meta_query, нужно объединять его с новым, иначе теряются условия.
  • Неочищенный кэш: изменения не видны из-за кэширования.

Как правильно объединить несколько meta_query

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

add_action('pre_get_posts', 'add_meta_query_condition');
function add_meta_query_condition($query) {
    if (!is_admin() && $query->is_main_query() && is_post_type_archive('product')) {
        $existing = $query->get('meta_query');
        if (!is_array($existing)) {
            $existing = array();
        }
        $existing[] = array(
            'key' => '_custom_label',
            'value' => 'new-arrival',
            'compare' => '='
        );
        $query->set('meta_query', $existing);
    }
}

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

  • Не используйте pre_get_posts для сложных фильтров с большим количеством условий — лучше создайте отдельный WP_Query.
  • Добавляйте индексы в базу данных на метаполя, которые часто используете в meta_query (особенно для WooCommerce).
  • Проверяйте, что ваши условия не создают слишком тяжёлые SQL-запросы, чтобы избежать замедления.
  • Используйте кэширование запросов (например, Object Cache) для часто повторяющихся условий.

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

МетодПлюсыМинусы
pre_get_postsИзменяет основной запрос без дополнительного кода шаблона; работает для любых страницМожно случайно изменить не тот запрос; нельзя использовать для сложных запросов
Создание нового WP_QueryМаксимальная гибкость; можно получить любые данныеНужно вручную выводить результаты; дублирование кода
Использование плагинов фильтрацииПростота настройки; много готовых функцийИзбыточность кода; может замедлять сайт; зависимость от обновлений
×
Сделай свой сайт крутым!

Скидка -20% на премиум плагины WordPress

Выбрать плагин сейчас ⋙