При работе с большими наборами данных в WordPress часто возникает потребность в реализации удобного и быстрого мультифильтра, позволяющего пользователям гибко выбирать нужные параметры и получать релевантные результаты без задержек. В этой статье разберем, как создать эффективный мультифильтр, который будет работать быстро и масштабируемо даже при больших объемах данных.
Зачем нужен мультифильтр и какие задачи он решает
Мультифильтр — это инструмент, который позволяет пользователю одновременно применять несколько фильтров по разным параметрам, например, фильтрация по категориям, меткам, ценам, датам и другим кастомным полям. Такой подход повышает удобство поиска и улучшает пользовательский опыт.
Однако при больших объемах данных фильтрация может значительно замедлять работу сайта, если запросы к базе данных не оптимизированы. Важно не только реализовать удобный интерфейс, но и продумать эффективную архитектуру запросов и кэширования.
На практике мультифильтр востребован в интернет-магазинах, каталогах, сайтах с большим количеством кастомных записей и метаданных.
Особенности реализации мультифильтра на WordPress
Основные особенности, которые нужно учесть при создании мультифильтра:
- Использование кастомных полей и таксономий — для хранения фильтруемых параметров;
- Оптимизация запросов — минимизация количества JOIN и использование индексов;
- Кэширование результатов — уменьшение нагрузки на базу данных;
- Асинхронная загрузка данных — AJAX для обновления результатов без перезагрузки страницы;
- Удобный и понятный UI — чтобы пользователь мог комфортно выбирать параметры.
Для реализации мультифильтра мы рассмотрим подход с WP_Query и мета-запросами, а также пример кэширования и AJAX.
Пример создания мультифильтра с кастомными полями и AJAX
1. Регистрация таксономий и кастомных полей
Для начала предположим, что у нас есть кастомный тип записи product и несколько таксономий: brand, color. А также мета-поля: price, size.
2. Создание формы фильтра в теме
Пример базовой формы с чекбоксами и полями для цены:
<form id="wpdata-multifilter">
<h3>Бренд</h3>
<?php
$brands = get_terms(['taxonomy' => 'brand', 'hide_empty' => false]);
foreach ($brands as $brand) {
echo '<label><input type="checkbox" name="brand[]" value="' . esc_attr($brand->slug) . '">' . esc_html($brand->name) . '</label><br>';
}
?>
<h3>Цвет</h3>
<?php
$colors = get_terms(['taxonomy' => 'color', 'hide_empty' => false]);
foreach ($colors as $color) {
echo '<label><input type="checkbox" name="color[]" value="' . esc_attr($color->slug) . '">' . esc_html($color->name) . '</label><br>';
}
?>
<h3>Цена</h3>
<label>От: <input type="number" name="price_min" min="0"></label>
<label>До: <input type="number" name="price_max" min="0"></label>
<button type="submit">Фильтровать</button>
</form>
<div id="wpdata-filter-results"></div>
3. Обработка AJAX запроса и формирование WP_Query
Добавим обработчик AJAX в functions.php или подключаемом файле плагина:
add_action('wp_ajax_wpdata_filter', 'wpdata_ajax_filter_handler');
add_action('wp_ajax_nopriv_wpdata_filter', 'wpdata_ajax_filter_handler');
function wpdata_ajax_filter_handler() {
$args = [
'post_type' => 'product',
'posts_per_page' => 10,
'tax_query' => [],
'meta_query' => [],
];
// Фильтрация по брендам
if (!empty($_POST['brand'])) {
$args['tax_query'][] = [
'taxonomy' => 'brand',
'field' => 'slug',
'terms' => array_map('sanitize_text_field', $_POST['brand']),
'operator' => 'IN',
];
}
// Фильтрация по цветам
if (!empty($_POST['color'])) {
$args['tax_query'][] = [
'taxonomy' => 'color',
'field' => 'slug',
'terms' => array_map('sanitize_text_field', $_POST['color']),
'operator' => 'IN',
];
}
// Объединение таксономий в один запрос
if (count($args['tax_query']) > 1) {
$args['tax_query']['relation'] = 'AND';
}
// Фильтрация по цене
$price_min = isset($_POST['price_min']) ? intval($_POST['price_min']) : 0;
$price_max = isset($_POST['price_max']) ? intval($_POST['price_max']) : 0;
if ($price_min > 0 || $price_max > 0) {
$meta_price = ['key' => 'price', 'type' => 'NUMERIC'];
if ($price_min > 0) {
$meta_price['value'][] = $price_min;
$meta_price['compare'] = '>=';
}
if ($price_max > 0) {
$meta_price['value'][] = $price_max;
$meta_price['compare'] = '<=';
}
if (count($meta_price['value']) == 2) {
$meta_price['value'] = [$price_min, $price_max];
$meta_price['compare'] = 'BETWEEN';
}
$args['meta_query'][] = $meta_price;
}
if (empty($args['meta_query'])) {
unset($args['meta_query']);
} else {
$args['meta_query']['relation'] = 'AND';
}
$query = new WP_Query($args);
if ($query->have_posts()) {
ob_start();
echo '<ul>';
while ($query->have_posts()) {
$query->the_post();
echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
}
echo '</ul>';
wp_reset_postdata();
$result = ob_get_clean();
} else {
$result = '<p>Нет результатов по вашему запросу.</p>';
}
wp_send_json_success($result);
}
4. JavaScript для отправки и получения результатов AJAX
Добавим скрипт в footer или подключим отдельным файлом:
document.getElementById('wpdata-multifilter').addEventListener('submit', function(e) {
e.preventDefault();
var formData = new FormData(this);
formData.append('action', 'wpdata_filter');
fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
method: 'POST',
credentials: 'same-origin',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('wpdata-filter-results').innerHTML = data.data;
} else {
document.getElementById('wpdata-filter-results').innerHTML = '<p>Ошибка при загрузке данных.</p>';
}
});
});
Оптимизация и кэширование запросов мультифильтра
Для повышения производительности при больших объемах данных стоит:
- Добавить индексы на мета-поля и таксономии в базе данных;
- Использовать объектный кэш WordPress или сторонние решения (Redis, Memcached);
- Кэшировать результаты AJAX запросов, например, с помощью transients API, учитывая параметры фильтра;
- Ограничивать количество загружаемых записей и использовать пагинацию;
- При необходимости использовать специализированные плагины, например, ABC Pagination для удобного отображения страниц.
Пример кэширования результатов в обработчике AJAX:
$cache_key = 'wpdata_filter_' . md5(serialize($args));
$result = get_transient($cache_key);
if (false === $result) {
// Выполняем запрос и формируем результат, как выше
// ...
set_transient($cache_key, $result, HOUR_IN_SECONDS);
}
wp_send_json_success($result);
Использование готовых решений для мультифильтров
Если вы хотите быстрее внедрить мультифильтр, можно рассмотреть плагины, которые поддерживают фильтрацию по кастомным полям и таксономиям, например:
- Clearfy Pro — содержит инструменты для оптимизации и расширения возможностей фильтрации;
- FacetWP — платный плагин с мощным AJAX-фильтром и поддержкой кастомных постов;
- Filter Everything — бесплатный плагин с гибкими настройками.
Однако при использовании плагинов всегда проверяйте влияние на производительность и совместимость с вашей темой и другими плагинами.
Заключение
Создание эффективного мультифильтра для больших наборов данных в WordPress — задача, требующая продуманного подхода к построению запросов, кэшированию и работе с AJAX. Используя примеры из статьи, вы сможете реализовать удобный и быстрый фильтр, который улучшит опыт пользователей и не создаст лишней нагрузки на сервер.