Фильтрация товаров WooCommerce по мета-полям с помощью pre_get_posts

Диагностика задачи: зачем фильтровать товары WooCommerce по мета-полям

Часто в интернет-магазинах на WooCommerce требуется показывать товары с определёнными характеристиками, которые хранятся в мета-полях (custom fields). Например, отобразить только товары со скидкой, товары с определённым цветом или из конкретной коллекции. Стандартные возможности WooCommerce не всегда позволяют гибко это сделать, особенно без плагинов.

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

Как фильтровать товары WooCommerce по мета-полям через pre_get_posts

Подключаем фильтр к основному запросу каталога

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

add_action('pre_get_posts', 'filter_woocommerce_products_by_meta');
function filter_woocommerce_products_by_meta($query) {
    if (is_admin() || !$query->is_main_query()) {
        return;
    }

    // Проверяем, что мы на архиве товаров WooCommerce
    if (is_post_type_archive('product') || is_tax('product_cat') || is_tax('product_tag')) {
        // Пример: фильтрация по мета-полю _custom_color со значением "red"
        $meta_query = array(
            array(
                'key' => '_custom_color',
                'value' => 'red',
                'compare' => '=',
            ),
        );

        // Если уже есть meta_query, объединяем
        if ($query->get('meta_query')) {
            $existing = $query->get('meta_query');
            $meta_query = array_merge($existing, $meta_query);
        }

        $query->set('meta_query', $meta_query);
        // Опционально: сортировка по цене
        //$query->set('orderby', 'meta_value_num');
        //$query->set('meta_key', '_price');
        //$query->set('order', 'ASC');
    }
}

Объяснение кода:

  • is_admin() и $query->is_main_query() — проверяем, что меняем только фронтенд основной запрос;
  • Условие is_post_type_archive('product') || is_tax('product_cat') || is_tax('product_tag') гарантирует, что фильтр сработает на страницах каталога и таксономий WooCommerce;
  • Создаём meta_query, чтобы отфильтровать товары по мета-полю _custom_color со значением red;
  • Если в запросе уже есть другие фильтры meta_query, мы объединяем их, чтобы не перезаписывать.

Проверка результата

Чтобы проверить, что фильтрация сработала:

  • Перейдите на страницу каталога товаров (например, /shop/ или категорию товаров).
  • Убедитесь, что отображаются только товары с мета-полем _custom_color равным red.
  • Для отладки можно временно добавить в функцию вывод SQL-запроса:
add_action('pre_get_posts', function($query) {
    if ($query->is_main_query() && !is_admin() && (is_post_type_archive('product') || is_tax('product_cat'))) {
        add_filter('posts_request', function($sql) {
            error_log($sql);
            return $sql;
        });
    }
});

Просмотрите лог ошибок PHP или debug.log, там будет SQL-запрос с фильтром.

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

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

Проверенный чек-лист для фильтрации товаров по мета-полям

  • Проверить, что хук добавлен с правильным приоритетом (обычно 10).
  • Убедиться, что условие для фильтрации корректно (архив товаров, категории, теги).
  • Использовать is_main_query() и !is_admin() для ограничения действия фильтра.
  • Если нужно, объединить новые условия meta_query с существующими.
  • Тестировать на локальной или staging-среде, чтобы избежать сбоев на рабочем сайте.
  • Проверить пагинацию и сортировку после добавления фильтра.

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

  • Не создавайте слишком сложных meta_query с большим количеством условий, это снизит скорость загрузки страниц.
  • Используйте transient caching для результатов сложных запросов, если данные не меняются часто.
  • Не выводите отладочную информацию в продакшене, используйте логирование.
  • Всегда тестируйте свои изменения на тестовом окружении перед продакшеном.
  • Если мета-поля хранят чувствительную информацию, убедитесь, что к ним нет открытого доступа через REST API или другие интерфейсы.

Сравнение способов фильтрации товаров WooCommerce по мета-полям

МетодПлюсыМинусы
pre_get_posts (код)Гибко, без плагинов, полный контроль над запросомТребует навыков, можно ошибиться с условиями, влияет на производительность
Плагины фильтрации (например, FacetWP, WOOF)Простая настройка, много опций, UI для пользователейНагрузка на сайт, платные версии, ограниченная кастомизация
Кастомные WP_Query в шаблонахИзолированный код, можно использовать в нужных местахНе всегда интегрируется с WooCommerce пагинацией и URL
Как создать динамический файл robots.txt в WordPress
08.03.2026
Как добавить автоматический сбор отзывов по email в WordPress
27.02.2026
Как создать настройку переключатель темы в WordPress с применением хуков
16.12.2025
Как создать автоматический кеш для REST API в WordPress
11.01.2026
Как добавить поддержку REST API в своем плагине WordPress
13.12.2025