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

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

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

Диагностика проблемы: почему стандартные фильтры не подходят

WooCommerce использует таксономии и атрибуты для фильтрации. Однако произвольные мета-поля (post meta) не интегрируются в фильтры по умолчанию, так как они хранятся в таблице wp_postmeta. Нужно вручную добавить логику вывода фильтра, обработки параметров запроса и корректной фильтрации через WP_Query.

Пошаговое решение: создание собственного фильтра по мета-полю

1. Добавляем HTML формы фильтра в шаблон архива товаров

Лучше всего использовать хук woocommerce_before_shop_loop для вывода формы фильтра перед списком товаров:

add_action('woocommerce_before_shop_loop', 'custom_meta_filter_form', 20); 
function custom_meta_filter_form() {
    $selected = isset($_GET['custom_meta_filter']) ? sanitize_text_field($_GET['custom_meta_filter']) : '';
    ?>
    <form method="GET" class="custom-meta-filter" style="margin-bottom:20px;">
        <label for="custom_meta_filter">Фильтр по коду товара:</label>
        <input type="text" name="custom_meta_filter" id="custom_meta_filter" value="<?php echo esc_attr($selected); ?>" />
        <button type="submit">Применить</button>
        <?php
        // Сохраняем остальные GET-параметры для корректной навигации
        foreach ($_GET as $key => $value) {
            if ($key !== 'custom_meta_filter' && $key !== 'paged') {
                echo '<input type="hidden" name="'.esc_attr($key).'" value="'.esc_attr($value).'" />';
            }
        }
        ?>
    </form>
    <?php
}

2. Модифицируем основной запрос WooCommerce для фильтрации по мета-полю

Для этого используем хук pre_get_posts и добавляем условие по мета-ключу:

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

    if (is_shop() || is_product_category() || is_product_tag()) {
        if (!empty($_GET['custom_meta_filter'])) {
            $meta_value = sanitize_text_field($_GET['custom_meta_filter']);
            $meta_query = array(
                array(
                    'key' => '_custom_code', // Замените на ваш мета ключ
                    'value' => $meta_value,
                    'compare' => 'LIKE',
                ),
            );
            $query->set('meta_query', $meta_query);
        }
    }
}

3. Добавляем в админке WooCommerce мета-поле для товаров

Если мета-поля ещё нет, например, _custom_code, добавим его через add_post_meta вручную или с помощью плагина типа Advanced Custom Fields. Пример добавления мета-поля к товару через код:

add_action('woocommerce_product_options_general_product_data', 'add_custom_code_field');
function add_custom_code_field() {
    woocommerce_wp_text_input(
        array(
            'id' => '_custom_code',
            'label' => __('Код товара', 'woocommerce'),
            'desc_tip' => 'true',
            'description' => __('Введите уникальный код товара', 'woocommerce'),
        )
    );
}

add_action('woocommerce_process_product_meta', 'save_custom_code_field');
function save_custom_code_field($post_id) {
    $custom_code = isset($_POST['_custom_code']) ? sanitize_text_field($_POST['_custom_code']) : '';
    update_post_meta($post_id, '_custom_code', $custom_code);
}

Проверка результата после внедрения

  • Перейдите в каталог товаров WooCommerce (страница магазина или категория).
  • В форме фильтра введите часть или полный код товара, который вы указали в мета-поле.
  • Нажмите «Применить» — список товаров должен отфильтроваться и показывать только те товары, у которых мета-поле _custom_code содержит введённый текст.
  • Если фильтр не сработал, проверьте наличие мета-полей у товаров и правильность подключения функций.

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

  • Фильтр не отображается: Проверьте, что хук woocommerce_before_shop_loop срабатывает на вашей теме. Если тема переопределяет шаблоны, вставьте форму вручную в archive-product.php.
  • Фильтрация не работает: Убедитесь, что ключ мета-поля в запросе совпадает с тем, что вы сохраняете у товаров.
  • Фильтр сбрасывается при пагинации: В форме обязательно сохраняйте все GET-параметры, кроме самой фильтрации и пагинации.
  • Большая нагрузка на сервер: Метапоиск с LIKE может быть медленным. Для больших каталогов лучше реализовать индексацию или использовать фильтры по таксономиям.

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

  • Санитизируйте все входящие данные через sanitize_text_field или более подходящие функции.
  • Для улучшения скорости фильтрации можно создать отдельную таксономию под нужные параметры и синхронизировать её с мета-полями.
  • Кэшируйте результаты запросов с помощью transient API, если фильтр используется часто с одними и теми же параметрами.
  • Если используете AJAX для фильтрации, обрабатывайте параметры через wp_ajax и wp_ajax_nopriv с nonce для безопасности.

Сравнение вариантов реализации фильтрации

МетодПреимуществаНедостатки
Фильтр по мета-полю (код выше)Гибкий, не требует изменения таксономийМожет быть медленным на больших базах данных
Создание кастомной таксономии и фильтр по нейБыстрая фильтрация, стандартные WooCommerce виджетыТребует синхронизации данных и миграции существующих мета-полей
Использование плагинов фильтрации (FacetWP, WOOF)Простая настройка, UI, поддержка AJAXПлатные, могут замедлять сайт
⭐⭐⭐⭐⭐