Диагностика задачи: зачем фильтровать товары 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 |