Создание динамического фильтра в WordPress для каталога

Для сайтов с каталогами товаров или услуг на WordPress важным элементом удобства для пользователей является фильтр поиска. Особенно если каталог содержит сотни или тысячи позиций, статический фильтр быстро станет неудобным. В этой статье мы подробно разберём, как создать динамический фильтр в WordPress, который будет подгружать только актуальные значения по выбранным параметрам, улучшая UX и снижая нагрузку на сервер.

Что такое динамический фильтр и зачем он нужен в каталоге WordPress

Динамический фильтр — это такой фильтр, который не просто отображает все возможные значения параметров, а меняет их в зависимости от уже выбранных пользователем опций. Например, если пользователь выбрал категорию «смартфоны», то в фильтре будут показаны только модели и бренды, доступные для этой категории, а не все подряд.

Это значительно облегчает поиск и повышает конверсию на сайте. Пользователь не увидит пустых результатов и не потеряется в огромном списке опций.

Реализовать динамический фильтр можно с помощью AJAX-запросов, которые подгружают новые варианты значений без перезагрузки страницы.

Выбор инструментов для реализации динамического фильтра

Для WordPress существует несколько подходов и плагинов, которые помогают создать фильтры:

  • FacetWP — мощный коммерческий плагин для динамических фильтров с поддержкой AJAX, но платный.
  • WPCatalog Filter — специализированный плагин для каталогов (возможно, стоит проверить на WPSHOP).
  • Собственная реализация на основе WP_Query, AJAX и кастомных таксономий.

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

Шаг 1. Создание пользовательских таксономий и полей для каталога

Чаще всего каталог товаров использует пользовательские типы записей (CPT) и таксономии (категории, бренды, характеристики).

Пример регистрации CPT и таксономии можно сделать так:

function wpcatalog_register_post_type_and_taxonomies() {
    register_post_type('wpcatalog_product', [
        'labels' => [
            'name' => 'Товары',
            'singular_name' => 'Товар'
        ],
        'public' => true,
        'has_archive' => true,
        'supports' => ['title', 'editor', 'thumbnail'],
    ]);

    register_taxonomy('wpcatalog_brand', 'wpcatalog_product', [
        'labels' => [
            'name' => 'Бренды',
            'singular_name' => 'Бренд'
        ],
        'hierarchical' => true,
        'public' => true
    ]);

    register_taxonomy('wpcatalog_feature', 'wpcatalog_product', [
        'labels' => [
            'name' => 'Характеристики',
            'singular_name' => 'Характеристика'
        ],
        'hierarchical' => false,
        'public' => true
    ]);
}
add_action('init', 'wpcatalog_register_post_type_and_taxonomies');

Так мы получим базу для каталога с товарами и связями по брендам и характеристикам.

Шаг 2. Вывод первоначального фильтра на страницу каталога

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

$brands = get_terms(['taxonomy' => 'wpcatalog_brand', 'hide_empty' => true]);
$features = get_terms(['taxonomy' => 'wpcatalog_feature', 'hide_empty' => true]);

Далее выводим их в форме:

<form id="wpcatalog-filter">
<h3>Бренды</h3>
<?php foreach ($brands as $brand): ?>
    <label>
        <input type="checkbox" name="brand[]" value="<?php echo esc_attr($brand->slug); ?>"> <?php echo esc_html($brand->name); ?>
    </label>
<?php endforeach; ?>

<h3>Характеристики</h3>
<?php foreach ($features as $feature): ?>
    <label>
        <input type="checkbox" name="feature[]" value="<?php echo esc_attr($feature->slug); ?>"> <?php echo esc_html($feature->name); ?>
    </label>
<?php endforeach; ?>

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

Этот фильтр мы сделаем AJAX, чтобы не перезагружать страницу.

Шаг 3. AJAX-запрос для динамической подгрузки вариантов фильтра

Основная идея динамического фильтра — при выборе параметров подгружать доступные значения других параметров. Для этого добавим JS, который будет отправлять выбранные фильтры на сервер.

Пример скрипта (подключите на странице каталога):

jQuery(document).ready(function($) {
    $('#wpcatalog-filter input[type=checkbox]').on('change', function() {
        var data = $('#wpcatalog-filter').serialize();
        $.ajax({
            url: wpcatalog_ajax_obj.ajax_url,
            type: 'POST',
            data: {
                action: 'wpcatalog_update_filter',
                filter: data
            },
            success: function(response) {
                // обновим контент фильтра и список товаров
                $('#wpcatalog-filter').html(response.filter_html);
                $('#wpcatalog-products').html(response.products_html);
            }
        });
    });
});

Не забудьте локализовать скрипт, чтобы передать ajax_url:

function wpcatalog_enqueue_scripts() {
    wp_enqueue_script('wpcatalog-filter', get_template_directory_uri() . '/js/wpcatalog-filter.js', ['jquery'], null, true);
    wp_localize_script('wpcatalog-filter', 'wpcatalog_ajax_obj', [
        'ajax_url' => admin_url('admin-ajax.php')
    ]);
}
add_action('wp_enqueue_scripts', 'wpcatalog_enqueue_scripts');

Шаг 4. Обработка AJAX-запроса на сервере

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

function wpcatalog_ajax_update_filter() {
    parse_str($_POST['filter'], $params);

    // Формируем аргументы WP_Query с фильтрами
    $tax_query = [];
    if (!empty($params['brand'])) {
        $tax_query[] = [
            'taxonomy' => 'wpcatalog_brand',
            'field' => 'slug',
            'terms' => $params['brand'],
            'operator' => 'IN'
        ];
    }
    if (!empty($params['feature'])) {
        $tax_query[] = [
            'taxonomy' => 'wpcatalog_feature',
            'field' => 'slug',
            'terms' => $params['feature'],
            'operator' => 'IN'
        ];
    }
    $query_args = [
        'post_type' => 'wpcatalog_product',
        'posts_per_page' => 20,
        'tax_query' => $tax_query ? ['relation' => 'AND'] + $tax_query : [],
    ];

    $products_query = new WP_Query($query_args);

    // Обновляем список товаров
    ob_start();
    if ($products_query->have_posts()) {
        echo '<ul class="wpcatalog-products-list">';
        while ($products_query->have_posts()) {
            $products_query->the_post();
            echo '<li>' . get_the_title() . '</li>';
        }
        echo '</ul>';
    } else {
        echo '<p>Товары не найдены</p>';
    }
    $products_html = ob_get_clean();

    // Обновляем фильтр — подгружаем только термины, которые есть в текущем наборе товаров
    $filtered_brands = wp_list_pluck(get_terms([ 'taxonomy' => 'wpcatalog_brand', 'hide_empty' => true ]), 'slug');
    $filtered_features = wp_list_pluck(get_terms([ 'taxonomy' => 'wpcatalog_feature', 'hide_empty' => true ]), 'slug');

    ob_start();
    // Выводим фильтр с активными чекбоксами и только доступными вариантами
    $all_brands = get_terms([ 'taxonomy' => 'wpcatalog_brand', 'hide_empty' => true ]);
    echo '<h3>Бренды</h3>';
    foreach ($all_brands as $brand) {
        if (in_array($brand->slug, $filtered_brands)) {
            $checked = in_array($brand->slug, $params['brand'] ?? []) ? 'checked' : '';
            echo '<label><input type="checkbox" name="brand[]" value="' . esc_attr($brand->slug) . '" ' . $checked . '> ' . esc_html($brand->name) . '</label>';
        }
    }

    $all_features = get_terms([ 'taxonomy' => 'wpcatalog_feature', 'hide_empty' => true ]);
    echo '<h3>Характеристики</h3>';
    foreach ($all_features as $feature) {
        if (in_array($feature->slug, $filtered_features)) {
            $checked = in_array($feature->slug, $params['feature'] ?? []) ? 'checked' : '';
            echo '<label><input type="checkbox" name="feature[]" value="' . esc_attr($feature->slug) . '" ' . $checked . '> ' . esc_html($feature->name) . '</label>';
        }
    }

    $filter_html = ob_get_clean();

    wp_send_json_success(['products_html' => $products_html, 'filter_html' => $filter_html]);
}
add_action('wp_ajax_wpcatalog_update_filter', 'wpcatalog_ajax_update_filter');
add_action('wp_ajax_nopriv_wpcatalog_update_filter', 'wpcatalog_ajax_update_filter');

Данная функция обрабатывает выбранные фильтры, возвращает обновлённый список товаров и варианты фильтров, которые актуальны для текущего результата.

Шаг 5. Дополнительные улучшения и советы

Оптимизация запросов

При большом каталоге стоит добавить кеширование результатов и использовать индексы в базе данных для таксономий. Также можно ограничивать количество загружаемых значений в фильтре.

Использование кастомных полей

Если у товаров есть числовые характеристики (цена, вес и т.п.), динамический фильтр можно расширить с помощью мета-запросов WP_Query и слайдеров для выбора диапазона.

Интеграция с плагинами WPSHOP

Для расширения функционала и упрощения настройки фильтров можно использовать плагин WPCatalog Filter от WPSHOP, который поддерживает AJAX и динамическое обновление. Он поможет быстро получить профессиональный результат без глубокого программирования.

Итог

Создание динамического фильтра в WordPress — задача вполне решаемая своими силами. Ключевое — грамотно организовать структуру данных, использовать AJAX для обновления и продумать UX. Приведённый пример кода можно взять за основу и адаптировать под свои нужды.

WooCommerce: не работают кнопки «Купить» после обновления — как исправить
09.05.2026
WooCommerce: автоматическое отключение товаров при нулевом остатке
20.05.2026
Как очистить базу данных WordPress от старых meta данных и оптимизировать сайт
13.03.2026
Как удалить или изменить meta robots в WordPress для улучшения SEO
05.01.2026
Как создать собственную таблицу в WordPress без плагинов
21.11.2025