Для сайтов с каталогами товаров или услуг на 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. Приведённый пример кода можно взять за основу и адаптировать под свои нужды.