В интернет-магазинах на WooCommerce фильтрация товаров — ключевой элемент удобства для покупателей. Если вы хотите создать динамический фильтр, который будет работать без сторонних плагинов, то эта статья поможет разобраться в этом вопросе детально. Мы создадим кастомный фильтр по атрибутам и цене, используя стандартные возможности WordPress и WooCommerce.
Почему стоит отказаться от плагинов фильтрации
Многие используют популярные плагины вроде WooCommerce Product Filter, FacetWP или Themify Filter. Они удобны, но имеют существенные минусы:
- Нагрузка на сайт — дополнительные скрипты и запросы замедляют загрузку.
- Конфликты с темами и другими плагинами — часто возникают проблемы совместимости.
- Зависимость от обновлений и поддержки разработчиков.
Создавая фильтр самостоятельно, вы получаете полный контроль над функционалом и оптимизацией.
Основы динамической фильтрации в WooCommerce
Фильтрация товаров в WooCommerce базируется на WP_Query и таксономиях. Атрибуты товаров — это таксономии, например, цвет, размер, бренд. Цена — это мета-поле. Для динамического фильтра нам нужно:
- Вывести форму с фильтрами, значения которых подтягиваются из базы.
- Обработать отправленные данные и изменить запрос товаров.
- Отобразить результаты без перезагрузки страницы (опционально).
Создание формы фильтра
Для начала сформируем форму, которая будет содержать чекбоксы с атрибутами и диапазон цен. Предположим, что у вас есть атрибут "Цвет" (pa_color).
<form method="GET" id="wordpresses-filter">
<h3>Цвет</h3>
<?php
$colors = get_terms(array(
'taxonomy' => 'pa_color',
'hide_empty' => true
));
foreach ($colors as $color) {
$checked = isset($_GET['filter_color']) && in_array($color->slug, $_GET['filter_color']) ? 'checked' : '';
echo '<label><input type="checkbox" name="filter_color[]" value="' . esc_attr($color->slug) . '" ' . $checked . '>' . esc_html($color->name) . '</label><br>';
}
?>
<h3>Цена</h3>
<label>От <input type="number" name="price_min" value="<?php echo esc_attr($_GET['price_min'] ?? ''); ?>" min="0"></label>
<label>До <input type="number" name="price_max" value="<?php echo esc_attr($_GET['price_max'] ?? ''); ?>" min="0"></label>
<button type="submit">Фильтровать</button>
</form>
Обработка фильтра на стороне запроса
Чтобы изменить отображаемые товары в зависимости от фильтра, нужно подключиться к фильтру woocommerce_product_query. В нем мы добавим условия для атрибутов и цены.
add_action('woocommerce_product_query', 'wordpresses_filter_products_query');
function wordpresses_filter_products_query($query) {
if (!is_admin() && is_shop()) {
$tax_query = array();
if (!empty($_GET['filter_color'])) {
$tax_query[] = array(
'taxonomy' => 'pa_color',
'field' => 'slug',
'terms' => array_map('sanitize_text_field', $_GET['filter_color']),
'operator' => 'IN',
);
}
if ($tax_query) {
$query->set('tax_query', $tax_query);
}
$meta_query = $query->get('meta_query') ? $query->get('meta_query') : array();
$price_min = isset($_GET['price_min']) ? floatval($_GET['price_min']) : 0;
$price_max = isset($_GET['price_max']) ? floatval($_GET['price_max']) : 0;
if ($price_min > 0 || $price_max > 0) {
$price_filter = array('key' => '_price');
if ($price_min > 0) {
$price_filter['value'][] = $price_min;
$price_filter['compare'] = '>=';
$price_filter['type'] = 'NUMERIC';
}
if ($price_max > 0) {
$price_filter['value'][] = $price_max;
$price_filter['compare'] = isset($price_filter['compare']) ? 'BETWEEN' : '<=';
$price_filter['type'] = 'NUMERIC';
}
if ($price_filter['compare'] === 'BETWEEN' && count($price_filter['value']) === 2) {
$price_filter['value'] = array($price_min, $price_max);
}
$meta_query[] = $price_filter;
}
if ($meta_query) {
$query->set('meta_query', $meta_query);
}
}
}
Опциональная AJAX-фильтрация
Для улучшения UX можно сделать отправку формы и обновление товаров без перезагрузки страницы через AJAX. Для этого нужно добавить JavaScript, который будет перехватывать отправку формы, отправлять запрос и обновлять блок с товарами.
Пример простого AJAX-запроса:
jQuery(document).ready(function($) {
$('#wordpresses-filter').on('submit', function(e) {
e.preventDefault();
var data = $(this).serialize();
$.ajax({
url: wc_add_to_cart_params.ajax_url,
type: 'GET',
data: data + '&action=wordpresses_filter_products',
success: function(response) {
$('#products-container').html(response);
}
});
});
});
И серверная обработка AJAX запроса:
add_action('wp_ajax_wordpresses_filter_products', 'wordpresses_filter_products_ajax');
add_action('wp_ajax_nopriv_wordpresses_filter_products', 'wordpresses_filter_products_ajax');
function wordpresses_filter_products_ajax() {
// Повторяем логику фильтрации из woocommerce_product_query
// И выводим товары, например, через wc_get_template_part('content', 'product')
$args = array(
'post_type' => 'product',
'posts_per_page' => 12,
// Здесь добавляем таксономии и мета-запросы по аналогии с хуком выше
);
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
wc_get_template_part('content', 'product');
}
} else {
echo '<p>Товары не найдены</p>';
}
wp_die();
}
Выводы и рекомендации
Динамический фильтр без плагинов — отличный способ оптимизировать сайт, уменьшить количество сторонних зависимостей и повысить скорость загрузки. Главное — внимательно работать с WP_Query и безопасно обрабатывать входящие данные.
Для более удобного UX не забудьте добавить индикаторы загрузки и поддержку истории браузера, чтобы пользователи могли сохранять ссылки с активными фильтрами.
Если хотите усовершенствовать функционал, можно интегрировать данный фильтр с плагином Clearfy Pro для оптимизации базы данных и кеширования запросов. Подробнее об этом на wpshop.ru.