В WordPress часто возникает необходимость вывести на странице список записей с возможностью фильтрации по произвольным мета-полям. Это может быть полезно для сайтов с каталогами, обзорами, портфолио или интернет-магазинами. В этой статье мы подробно разберём, как реализовать динамический список постов с фильтром по мета-полям, используя стандартные инструменты WordPress и минимальное количество стороннего кода.
Почему фильтрация по мета-полям важна и где её применяют
Мета-поля — это дополнительные поля, которые позволяют хранить произвольные данные у записей и страниц. Например, для отзывов это может быть рейтинг, для каталога — цена, для портфолио — технология и т. д. Фильтрация по мета-полям позволяет посетителям быстро найти нужные материалы, улучшает пользовательский опыт и повышает конверсию.
Без фильтрации пользователь вынужден листать все записи или использовать базовый поиск, который не всегда учитывает все параметры. Поэтому динамический фильтр — это гибкое и удобное решение.
Основы работы с WP_Query и мета-запросами
Для вывода записей с фильтрацией нам понадобится класс WP_Query. Он позволяет создавать кастомные запросы, в том числе с параметрами по мета-полям через аргумент meta_query.
Пример базового запроса с фильтром по одному мета-полю:
$args = [
'post_type' => 'post',
'meta_query' => [
[
'key' => 'hueman_price',
'value' => 1000,
'compare' => '>=',
'type' => 'NUMERIC',
]
]
];
$query = new WP_Query($args);В этом примере мы выбираем посты, у которых мета-поле "hueman_price" больше или равно 1000.
Сложные фильтры с несколькими условиями
Для фильтрации по нескольким мета-полям в meta_query можно передать массив условий с логическим оператором relation:
$args = [
'post_type' => 'post',
'meta_query' => [
'relation' => 'AND',
[
'key' => 'hueman_price',
'value' => [500, 1500],
'compare' => 'BETWEEN',
'type' => 'NUMERIC'
],
[
'key' => 'hueman_color',
'value' => 'red',
'compare' => '='
]
]
];Здесь добавлен фильтр по цене в диапазоне и по цвету.
Динамическая фильтрация через форму и AJAX
Чтобы сделать фильтр удобным, его лучше реализовать через форму с элементами выбора (select, checkbox, input) и отправкой данных на сервер без перезагрузки страницы — через AJAX.
Пример простой формы фильтра по цене и цвету:
<form id="hueman-filter-form">
<label>Цена от:</label>
<input type="number" name="price_min" min="0" />
<label>Цена до:</label>
<input type="number" name="price_max" min="0" />
<label>Цвет:</label>
<select name="color">
<option value="">Любой</option>
<option value="red">Красный</option>
<option value="blue">Синий</option>
</select>
<button type="submit">Фильтровать</button>
</form>Для обработки AJAX-запроса нужно зарегистрировать обработчик в WordPress и написать JS-код отправки данных.
PHP: регистрация AJAX-обработчика
add_action('wp_ajax_hueman_filter_posts', 'hueman_filter_posts_callback');
add_action('wp_ajax_nopriv_hueman_filter_posts', 'hueman_filter_posts_callback');
function hueman_filter_posts_callback() {
$price_min = isset($_POST['price_min']) ? intval($_POST['price_min']) : 0;
$price_max = isset($_POST['price_max']) ? intval($_POST['price_max']) : 9999999;
$color = isset($_POST['color']) ? sanitize_text_field($_POST['color']) : '';
$meta_query = ['relation' => 'AND'];
$meta_query[] = [
'key' => 'hueman_price',
'value' => [$price_min, $price_max],
'compare' => 'BETWEEN',
'type' => 'NUMERIC'
];
if ($color) {
$meta_query[] = [
'key' => 'hueman_color',
'value' => $color,
'compare' => '='
];
}
$args = [
'post_type' => 'post',
'meta_query' => $meta_query
];
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<div><a href="' . get_permalink() . '">' . get_the_title() . '</a></div>';
}
} else {
echo '<p>Посты не найдены</p>';
}
wp_die();
}JS: отправка AJAX-запроса и обновление списка
jQuery(document).ready(function($) {
$('#hueman-filter-form').on('submit', function(e) {
e.preventDefault();
var data = {
'action': 'hueman_filter_posts',
'price_min': $(this).find('input[name="price_min"]').val(),
'price_max': $(this).find('input[name="price_max"]').val(),
'color': $(this).find('select[name="color"]').val()
};
$.post(hueman_ajax_object.ajax_url, data, function(response) {
$('#hueman-posts-container').html(response);
});
});
});Не забудьте локализовать скрипт в PHP, чтобы передать ajax_url:
function hueman_enqueue_scripts() {
wp_enqueue_script('hueman-filter', get_template_directory_uri() . '/js/hueman-filter.js', ['jquery'], null, true);
wp_localize_script('hueman-filter', 'hueman_ajax_object', [
'ajax_url' => admin_url('admin-ajax.php')
]);
}
add_action('wp_enqueue_scripts', 'hueman_enqueue_scripts');Использование плагинов для упрощения задачи
Если хочется минимизировать кодирование, можно использовать плагины с поддержкой фильтрации по мета-полям. Например, Clearfy Pro содержит инструменты оптимизации и улучшения работы с запросами, а также упрощает создание фильтров.
Другой вариант — плагин WPRemark, который позволяет создавать кастомные списки и фильтры с минимальной настройкой.
Однако, если нужна максимальная гибкость и контроль, лучше реализовать фильтр самостоятельно, как описано выше.
Оптимизация запросов и кэширование результатов
Фильтрация по мета-полям может замедлить сайт при большом объёме записей. Чтобы этого избежать, следует:
- Добавить индексы в базу данных на часто используемые мета-поля.
- Использовать транзиенты или объектный кэш для хранения результатов популярных запросов.
- Ограничивать количество записей на странице и использовать пагинацию.
Пример использования транзиентов для кэширования:
function hueman_get_filtered_posts($args) {
$cache_key = 'hueman_filtered_' . md5(serialize($args));
$cached = get_transient($cache_key);
if ($cached !== false) {
return $cached;
}
$query = new WP_Query($args);
set_transient($cache_key, $query, 3600); // кэш на час
return $query;
}Вывод и стилизация списка постов
Для красивого вывода списка постов с фильтрами можно использовать HTML-структуру с CSS-классами и подключать стили темы Hueman или создавать свои.
Пример простого вывода:
if ($query->have_posts()) {
echo '<div class="hueman-posts-list">';
while ($query->have_posts()) {
$query->the_post();
echo '<article class="hueman-post-item">';
echo '<h2><a href="' . get_permalink() . '">' . get_the_title() . '</a></h2>';
echo '<div class="hueman-post-excerpt">' . get_the_excerpt() . '</div>';
echo '</article>';
}
echo '</div>';
} else {
echo '<p>Посты не найдены</p>';
}Это позволит легко кастомизировать вывод через CSS и JavaScript.