Адаптивный фильтр товаров на WooCommerce: создание без плагинов

Фильтрация товаров — одна из ключевых функций интернет-магазина на WooCommerce. Часто владельцы магазинов используют готовые плагины для фильтрации, однако они могут замедлять сайт и перегружать админку. В этой статье мы подробно разберем, как создать адаптивный и легковесный фильтр товаров на WooCommerce без использования сторонних плагинов.

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

Готовые плагины, например, FacetWP, WOOF или Product Filter, действительно удобны, но имеют ряд минусов:

  • Увеличение нагрузки на сервер из-за дополнительных запросов;
  • Нередко плагины конфликтуют с темой или другими расширениями;
  • Ограниченные возможности кастомизации под конкретный дизайн и бизнес-логику;
  • Платные версии могут быть дорогими.

Создавая свой фильтр, вы получаете полный контроль над функционалом, минимизируете нагрузку и лучше интегрируете фильтрацию в дизайн.

Основы работы с WP_Query и параметрами фильтрации

WooCommerce использует класс WC_Query, основанный на WP_Query. Для фильтрации товаров нужно модифицировать параметры запроса, основываясь на выбранных пользователем критериях.

К основным критериям фильтрации относятся:

  • Категории товаров;
  • Атрибуты (цвет, размер, бренд и др.);
  • Цена;
  • Наличие на складе;
  • Рейтинг и другие метаданные.

Чтобы отфильтровать товары без плагинов, нам нужно добавить обработку GET-параметров в запрос.

Пример фильтрации по категории и атрибуту

Допустим, у нас есть атрибут pa_color и категория товара. В файле шаблона архива товаров или в функции фильтрации запроса добавим:

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

    $tax_query = array();

    if (!empty($_GET['product_cat'])) {
        $tax_query[] = array(
            'taxonomy' => 'product_cat',
            'field'    => 'slug',
            'terms'    => sanitize_text_field($_GET['product_cat']),
        );
    }

    if (!empty($_GET['pa_color'])) {
        $tax_query[] = array(
            'taxonomy' => 'pa_color',
            'field'    => 'slug',
            'terms'    => sanitize_text_field($_GET['pa_color']),
        );
    }

    if ($tax_query) {
        $query->set('tax_query', $tax_query);
    }
}

Этот код добавляет фильтрацию товаров по категории и цвету, если соответствующие параметры есть в URL.

Создание фронтенд-формы фильтрации

Чтобы пользователи могли выбирать фильтры, нужно вывести HTML-форму с нужными полями. Пример формы фильтрации по категориям и цвету:

<form method="get" action="" id="wp0-product-filter">
    <label for="product_cat">Категория:</label>
    <select name="product_cat" id="product_cat">
        <option value="">Все категории</option>
        <?php
        $categories = get_terms('product_cat', array('hide_empty' => true));
        foreach ($categories as $category) {
            $selected = (isset($_GET['product_cat']) && $_GET['product_cat'] === $category->slug) ? 'selected' : '';
            echo "<option value=\"{$category->slug}\" $selected>{$category->name}</option>";
        }
        ?>
    </select>

    <label for="pa_color">Цвет:</label>
    <select name="pa_color" id="pa_color">
        <option value="">Все цвета</option>
        <?php
        $colors = get_terms('pa_color', array('hide_empty' => true));
        foreach ($colors as $color) {
            $selected = (isset($_GET['pa_color']) && $_GET['pa_color'] === $color->slug) ? 'selected' : '';
            echo "<option value=\"{$color->slug}\" $selected>{$color->name}</option>";
        }
        ?>
    </select>

    <button type="submit">Фильтровать</button>
</form>

Форма отправляет выбранные параметры методом GET, которые мы обрабатываем в функции фильтрации.

Добавление фильтра по цене с использованием мета-запросов

Фильтрация по цене — одна из самых популярных задач. WooCommerce хранит цену в метаполе _price. Для фильтрации по диапазону стоимости используйте параметр meta_query.

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

    $meta_query = $query->get('meta_query');
    if (!is_array($meta_query)) {
        $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', 'type' => 'NUMERIC');

        if ($price_min > 0) {
            $price_filter['value'][] = $price_min;
            $price_filter['compare'] = '>=';
        }

        if ($price_max > 0) {
            $price_filter['value'][] = $price_max;
            $price_filter['compare'] = $price_min > 0 ? 'BETWEEN' : '<=';
        }

        if ($price_min > 0 && $price_max > 0) {
            $price_filter['value'] = array($price_min, $price_max);
            $price_filter['compare'] = 'BETWEEN';
        }

        $meta_query[] = $price_filter;
    }

    $query->set('meta_query', $meta_query);
}

Добавим к форме фильтра поля для минимальной и максимальной цены:

<label for="price_min">Цена от:</label>
<input type="number" name="price_min" id="price_min" value="<?php echo isset($_GET['price_min']) ? esc_attr($_GET['price_min']) : ''; ?>" step="0.01" min="0" />

<label for="price_max">Цена до:</label>
<input type="number" name="price_max" id="price_max" value="<?php echo isset($_GET['price_max']) ? esc_attr($_GET['price_max']) : ''; ?>" step="0.01" min="0" />

Оптимизация и кеширование фильтрации

Чтобы фильтр работал быстро даже на больших каталогах, важно оптимизировать запросы и использовать кеширование. Рекомендуется:

  • Использовать индексы в базе данных для метаполей и таксономий;
  • Кешировать результаты запроса с помощью Transients API;
  • Минимизировать количество запросов и не делать тяжелые JOIN’ы;
  • Ограничивать количество одновременно выбранных фильтров.

Для кеширования можно добавить в функцию фильтрации проверку и сохранение результата так:

function wp0_get_filtered_products() {
    $cache_key = 'wp0_filtered_products_' . md5(serialize($_GET));
    $cached = get_transient($cache_key);
    if ($cached !== false) {
        return $cached;
    }

    $args = array(
        'post_type' => 'product',
        'posts_per_page' => 12,
        // параметры фильтрации из $_GET
    );

    $query = new WP_Query($args);
    set_transient($cache_key, $query->posts, 3600); // кеш на 1 час
    return $query->posts;
}

Советы по улучшению UX фильтра

Чтобы пользователи с удовольствием использовали фильтр, нужно сделать его удобным:

  • Добавить кнопку сброса всех фильтров;
  • Использовать AJAX для обновления списка без перезагрузки страницы (пример с использованием jQuery и admin-ajax.php можно реализовать отдельно);
  • Показывать количество товаров рядом с каждым фильтром;
  • Делать фильтры интуитивно понятными и компактными.

Использование плагинов WPGPT и Clearfy Pro для расширения фильтрации

Для тех, кто хочет упростить процесс создания фильтров и повысить производительность сайта, можно рекомендовать плагины из экосистемы WPGPT и Clearfy Pro.

WPGPT помогает создавать динамические фильтры на основе искусственного интеллекта для улучшения поиска товаров, а Clearfy Pro оптимизирует работу сайта и устраняет избыточные запросы, что положительно сказывается на скорости загрузки страниц с фильтрами.

Использование этих инструментов совместно с собственными решениями по фильтрации позволит получить более мощный и быстрый функционал.

Наш каталог плагинов WordPress