Фильтрация записей по пользовательским мета-полям — одна из частых задач при создании сложных и удобных интерфейсов на сайтах WordPress. Это особенно актуально, когда нужно отобразить только те записи, которые соответствуют нескольким параметрам, заданным пользователем. В этой статье мы подробно разберём, как создать уникальный AJAX-фильтр по пользовательским мета-полям без использования громоздких плагинов, с примерами кода и советами по оптимизации.
Почему важно использовать мета-поля для фильтрации и какие есть сложности
Пользовательские мета-поля (custom fields) позволяют хранить дополнительную информацию о записи. Например, для товаров это может быть цвет, размер, материал, для события — дата и место проведения. Фильтрация по этим полям позволяет посетителям быстро находить нужный контент.
Однако при большом объёме данных и сложных запросах к базе данных производительность может серьёзно пострадать. Стандартный WP_Query позволяет фильтровать по meta_query, но при множественных условиях запросы становятся медленными. Поэтому важно правильно строить запросы и оптимизировать базу данных.
Также стоит учитывать, что мета-поля хранятся в таблице wp_postmeta, которая может быстро разрастаться, и индексация играет ключевую роль в скорости выборки.
Создание AJAX-фильтра по пользовательским мета-полям: разбор задачи
Задача — сделать на сайте фильтр, который позволяет пользователям выбирать значения нескольких мета-полей (например, цвет и размер) и получать список записей, которые соответствуют выбранным параметрам, без перезагрузки страницы.
Основные этапы решения:
- Вывод формы фильтра с перечнем значений мета-полей.
- Обработка AJAX-запроса на сервере.
- Формирование WP_Query с условиями meta_query.
- Отправка результата обратно на фронтенд и динамическое обновление контента.
Форма фильтра с пользовательскими мета-полями
Для начала создадим простую HTML-форму с чекбоксами для двух мета-полей: color и size.
<form id="wplessons-filter">
<h3>Цвет</h3>
<label><input type="checkbox" name="color[]" value="red"> Красный</label>
<label><input type="checkbox" name="color[]" value="blue"> Синий</label>
<label><input type="checkbox" name="color[]" value="green"> Зеленый</label>
<h3>Размер</h3>
<label><input type="checkbox" name="size[]" value="small"> Маленький</label>
<label><input type="checkbox" name="size[]" value="medium"> Средний</label>
<label><input type="checkbox" name="size[]" value="large"> Большой</label>
<button type="submit">Применить</button>
</form>
<div id="wplessons-filter-results"></div>
В этой форме пользователь выбирает значения, по которым будет фильтрация.
JavaScript для отправки AJAX-запроса
Подключим скрипт, который будет перехватывать отправку формы и посылать данные на сервер.
document.getElementById('wplessons-filter').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const params = new URLSearchParams();
for (const pair of formData) {
params.append(pair[0], pair[1]);
}
fetch(wplessons_ajax_object.ajax_url + '?action=wplessons_filter_posts', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
body: params.toString()
})
.then(response => response.text())
.then(html => {
document.getElementById('wplessons-filter-results').innerHTML = html;
})
.catch(console.error);
});
Важно, что в WordPress нужно локализовать скрипт и передать ajax_url через wp_localize_script.
Обработка AJAX-запроса на стороне сервера
В functions.php или в своём плагине регистрируем обработчик AJAX:
add_action('wp_ajax_wplessons_filter_posts', 'wplessons_filter_posts_callback');
add_action('wp_ajax_nopriv_wplessons_filter_posts', 'wplessons_filter_posts_callback');
function wplessons_filter_posts_callback() {
$colors = isset($_POST['color']) ? array_map('sanitize_text_field', (array) $_POST['color']) : [];
$sizes = isset($_POST['size']) ? array_map('sanitize_text_field', (array) $_POST['size']) : [];
$meta_query = ['relation' => 'AND'];
if (!empty($colors)) {
$meta_query[] = [
'key' => 'color',
'value' => $colors,
'compare' => 'IN'
];
}
if (!empty($sizes)) {
$meta_query[] = [
'key' => 'size',
'value' => $sizes,
'compare' => 'IN'
];
}
$args = [
'post_type' => 'post',
'posts_per_page' => 10,
'meta_query' => $meta_query
];
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<h4><a href="' . get_permalink() . '">' . get_the_title() . '</a></h4>';
echo '<p>' . get_the_excerpt() . '</p>';
}
} else {
echo '<p>По вашему запросу ничего не найдено.</p>';
}
wp_reset_postdata();
wp_die();
}
Этот код формирует запрос по выбранным мета-полям, возвращает список постов с заголовками и отрывками.
Оптимизация и расширение фильтра
Индексация мета-полей
Для ускорения запросов по мета-полям имеет смысл добавить индексы в базу данных:
ALTER TABLE wp_postmeta ADD INDEX meta_key(meta_key(191));
ALTER TABLE wp_postmeta ADD INDEX meta_value(meta_value(191));
Это существенно повысит скорость выборки при большом количестве записей.
Кэширование результатов
Если фильтр используется часто с одинаковыми параметрами, можно кешировать результаты с помощью Transients API или объектов кеша, чтобы снизить нагрузку на базу.
Поддержка пагинации
В примере показано 10 записей, но можно добавить пагинацию, передавая номер страницы через AJAX и используя параметр paged в WP_Query.
Использование плагинов для упрощения
Если хочется не писать код с нуля, для подобных задач есть хорошие плагины, например, ABC Pagination — удобный инструмент для кастомной пагинации и AJAX-загрузки.
Заключение
Создание уникального фильтра по пользовательским мета-полям — задача, требующая понимания работы WP_Query и AJAX. Приведённый пример демонстрирует базовый подход, который можно развить под любые нужды, добавив больше условий, типов записей и улучшив интерфейс.
Такой фильтр значительно улучшит UX сайта и поможет пользователям быстро находить релевантный контент без лишних перезагрузок.