Диагностика задачи: зачем фильтровать товары WooCommerce через pre_get_posts
В стандартном WooCommerce фильтрация товаров обычно осуществляется через встроенные виджеты или параметры URL, например, по категориям или атрибутам. Однако, иногда требуется более тонкая кастомизация выборки товаров — например, исключить определённые товары из каталога, изменить порядок сортировки по условию или добавить условия выборки на нестандартных страницах.
Хук pre_get_posts позволяет вмешаться в основной WP_Query до выполнения запроса и задать необходимые параметры выборки. Это гораздо эффективнее, чем последующая фильтрация результатов, и не требует изменений в шаблонах.
Как правильно использовать pre_get_posts для WooCommerce
Пошаговое решение
- Подключитесь к хуку
pre_get_postsв файлеfunctions.phpвашей темы или в отдельном плагине. - Проверьте, что запрос основной (
$query->is_main_query()) и что мы находимся на нужной странице WooCommerce (например, архив товаров). - Добавьте условия выборки через методы
setобъекта$query.
add_action('pre_get_posts', 'custom_woocommerce_product_filter');
function custom_woocommerce_product_filter($query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
// Пример: фильтруем только на странице магазина WooCommerce
if (is_post_type_archive('product') || is_tax('product_cat')) {
// Исключаем товары с ID 10 и 20
$query->set('post__not_in', array(10, 20));
// Устанавливаем сортировку по цене по возрастанию
$query->set('meta_key', '_price');
$query->set('orderby', 'meta_value_num');
$query->set('order', 'ASC');
// Можно добавить дополнительные параметры, например, выводить только товары со статусом 'instock'
$meta_query = $query->get('meta_query');
if (!is_array($meta_query)) {
$meta_query = [];
}
$meta_query[] = [
'key' => '_stock_status',
'value' => 'instock'
];
$query->set('meta_query', $meta_query);
}
}Как проверить, что фильтр сработал
- Откройте страницу магазина WooCommerce (например, /shop/).
- Проверьте, что товары с ID 10 и 20 отсутствуют в списке.
- Убедитесь, что товары отображаются в порядке возрастания цены.
- Проверьте статус товара в админке — должны отображаться только товары со статусом «В наличии».
Расширенные сценарии фильтрации товаров
Фильтрация по пользовательским полям и атрибутам
Для фильтрации по атрибутам или произвольным полям используйте мета-запросы (meta_query) или таксономии (tax_query).
add_action('pre_get_posts', 'filter_products_by_attribute');
function filter_products_by_attribute($query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
if (is_post_type_archive('product')) {
$tax_query = $query->get('tax_query');
if (!is_array($tax_query)) {
$tax_query = [];
}
$tax_query[] = [
'taxonomy' => 'pa_color', // таксономия атрибута, например цвет
'field' => 'slug',
'terms' => 'red', // фильтруем по красному цвету
'operator' => 'IN',
];
$query->set('tax_query', $tax_query);
}
}Чек-лист: как правильно реализовать фильтрацию через pre_get_posts
- Подключайтесь только к основному запросу (
is_main_query()). - Не вмешивайтесь в административную часть (
is_admin()). - Правильно определяйте условия страниц (
is_post_type_archive('product'),is_tax()). - Используйте
setдля изменения параметров запроса. - Для мета-полей применяйте
meta_query, для атрибутов —tax_query. - Проверяйте результат на фронтенде, чтобы убедиться, что фильтрация работает.
Частые ошибки и как их исправить
Ошибка 1: фильтр не работает, товары не меняются
Причина: условие is_main_query() или is_post_type_archive('product') не срабатывает. Обычно это из-за того, что фильтр подключён слишком рано или используется на неправильной странице.
Решение: убедитесь, что хук pre_get_posts подключён к действию add_action('pre_get_posts', ...), и что проверка условий корректна.
Ошибка 2: фильтрация ломает пагинацию
Причина: изменение параметров запроса без учёта пагинации.
Решение: не меняйте параметры posts_per_page без необходимости и проверьте, что paged передаётся в запрос.
Ошибка 3: конфликт с другими плагинами WooCommerce
Причина: другие плагины тоже изменяют pre_get_posts и перезаписывают параметры.
Решение: используйте приоритеты в add_action, например add_action('pre_get_posts', 'your_func', 20), чтобы контролировать порядок выполнения.
Практические советы по безопасности и производительности
- Не выполняйте тяжелые запросы или сложные вычисления внутри
pre_get_posts, чтобы не замедлять загрузку страниц. - При фильтрации по мета-полям убедитесь, что соответствующие поля индексированы в базе данных для ускорения запросов.
- Используйте кэширование страниц и объектов (например, Object Cache) для снижения нагрузки при сложных фильтрах.
- Тестируйте изменения на тестовом сервере перед выкатыванием на продакшн.
Сравнение подходов к фильтрации товаров WooCommerce
| Метод | Преимущества | Недостатки |
|---|---|---|
| pre_get_posts | Гибкость, изменение основного запроса, высокая производительность | Требует знаний WP_Query, можно сломать пагинацию |
| WP_Query с новым запросом | Изолированность, не влияет на основной запрос | Дополнительные ресурсы, дублирование кода |
| Shortcode с кастомным выводом | Простота вставки в контент | Не меняет страницы архива, может влиять на SEO |