В работе с WordPress часто возникает задача сделать удобный и функциональный фильтр записей (постов), который позволит пользователям выбирать записи по нескольким параметрам одновременно. В этой статье разберём, как создать именно такой комплексный фильтр с несколькими условиями — например, по категории, таксономии, метаполям и дате.
Понимание задачи: что такое комплексный фильтр записей WordPress
Простой фильтр часто ограничивается выбором одной категории или одного параметра. Комплексный фильтр — это инструмент, который позволяет комбинировать несколько условий, например:
- Выбрать записи из нескольких категорий или по нескольким меткам;
- Отфильтровать по кастомным полям (метаполям), например, цене, рейтингу или дате;
- Использовать логические операторы AND, OR для более гибкого поиска;
- Поддерживать AJAX-загрузку для обновления результатов без перезагрузки страницы.
Все это можно реализовать и без плагинов, используя WP_Query и кастомные формы, либо с использованием специальных плагинов для фильтрации.
Использование WP_Query для нескольких условий: практический пример
Рассмотрим пример, когда нам нужно вывести записи, которые находятся в категории с ID 10, имеют мета-поле price больше 1000, и опубликованы после 1 января 2023 года.
Основной инструмент — класс WP_Query с передачей массива параметров.
$args = [
'post_type' => 'post',
'posts_per_page' => 10,
'category__in' => [10],
'meta_query' => [
[
'key' => 'price',
'value' => 1000,
'compare' => '>',
'type' => 'NUMERIC',
],
],
'date_query' => [
[
'after' => '2023-01-01',
'inclusive' => true,
],
],
];
$query = new WP_Query($args);Далее выводим записи в цикле:
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<h2>' . get_the_title() . '</h2>';
echo '<div>' . get_the_excerpt() . '</div>';
}
wp_reset_postdata();
} else {
echo 'Записи не найдены';
}Создание формы фильтра с несколькими полями
Чтобы фильтр был интерактивным, нужна форма с несколькими полями, например:
- Выбор категории (выпадающий список);
- Минимальная и максимальная цена (текстовые поля);
- Выбор даты публикации (два поля: с и по);
- Дополнительные таксономии или пользовательские поля.
Пример HTML-формы:
<form method="GET" id="wppremium-filter" action="">
<select name="category">
<option value="">Выберите категорию</option>
<?php
$categories = get_categories();
foreach ($categories as $cat) {
echo '<option value="' . $cat->term_id . '"' . (isset($_GET['category']) && $_GET['category'] == $cat->term_id ? ' selected' : '') . '>' . $cat->name . '</option>';
}
?>
</select>
<input type="number" name="price_min" placeholder="Минимальная цена" value="<?php echo esc_attr($_GET['price_min'] ?? ''); ?>" />
<input type="number" name="price_max" placeholder="Максимальная цена" value="<?php echo esc_attr($_GET['price_max'] ?? ''); ?>" />
<input type="date" name="date_from" value="<?php echo esc_attr($_GET['date_from'] ?? ''); ?>" />
<input type="date" name="date_to" value="<?php echo esc_attr($_GET['date_to'] ?? ''); ?>" />
<button type="submit">Фильтровать</button>
</form>Обработка параметров формы и создание запроса WP_Query
В PHP нужно собрать параметры GET-запроса, сформировать массив $args для WP_Query, учитывая все переданные условия.
function wppremium_build_filter_query() {
$args = [
'post_type' => 'post',
'posts_per_page' => 10,
'meta_query' => [],
'date_query' => [],
];
if (!empty($_GET['category'])) {
$args['category__in'] = [(int) $_GET['category']];
}
if (!empty($_GET['price_min']) || !empty($_GET['price_max'])) {
$price_filter = ['key' => 'price', 'type' => 'NUMERIC'];
if (!empty($_GET['price_min'])) {
$price_filter['value'][] = (int) $_GET['price_min'];
$price_filter['compare'] = '>=';
}
if (!empty($_GET['price_max'])) {
if (isset($price_filter['value'])) {
$price_filter['value'][] = (int) $_GET['price_max'];
$price_filter['compare'] = 'BETWEEN';
} else {
$price_filter['value'] = (int) $_GET['price_max'];
$price_filter['compare'] = '<=';
}
}
$args['meta_query'][] = $price_filter;
}
if (!empty($_GET['date_from']) || !empty($_GET['date_to'])) {
$date_filter = [];
if (!empty($_GET['date_from'])) {
$date_filter['after'] = sanitize_text_field($_GET['date_from']);
}
if (!empty($_GET['date_to'])) {
$date_filter['before'] = sanitize_text_field($_GET['date_to']);
}
$date_filter['inclusive'] = true;
$args['date_query'][] = $date_filter;
}
// Если meta_query пустой, убрать его чтобы не мешать запросу
if (empty($args['meta_query'])) {
unset($args['meta_query']);
}
// Если date_query пустой, убрать его
if (empty($args['date_query'])) {
unset($args['date_query']);
}
return $args;
}
// Использование
$args = wppremium_build_filter_query();
$query = new WP_Query($args);Добавление AJAX для обновления результатов без перезагрузки
Чтобы улучшить UX, можно сделать так, чтобы по изменению параметров фильтра страница не перезагружалась, а результаты обновлялись динамически.
Общий алгоритм:
- С помощью JavaScript отлавливать событие отправки формы или изменения параметров;
- Посылать AJAX-запрос на сервер с параметрами фильтра;
- На сервере обрабатывать запрос с помощью WP_Query и возвращать HTML с результатами;
- Обновлять контент страницы на клиенте.
Пример jQuery-кода для отправки AJAX:
jQuery(document).ready(function($) {
$('#wppremium-filter').on('submit', function(e) {
e.preventDefault();
var data = $(this).serialize();
$.ajax({
url: wppremium_ajax_object.ajax_url,
method: 'POST',
data: {
action: 'wppremium_filter_posts',
filter: data
},
success: function(response) {
$('#wppremium-results').html(response);
}
});
});
});Пример обработки AJAX в functions.php:
add_action('wp_ajax_wppremium_filter_posts', 'wppremium_ajax_filter_posts');
add_action('wp_ajax_nopriv_wppremium_filter_posts', 'wppremium_ajax_filter_posts');
function wppremium_ajax_filter_posts() {
parse_str($_POST['filter'], $filter_params);
$_GET = $filter_params; // для использования функции построения запроса
$args = wppremium_build_filter_query();
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<h2>' . get_the_title() . '</h2>';
echo '<div>' . get_the_excerpt() . '</div>';
}
} else {
echo 'Результаты не найдены';
}
wp_die();
}Использование плагинов для расширения возможностей фильтра
Если хочется получить еще больше функционала с минимальными усилиями, можно обратить внимание на плагины:
- Clearfy Pro — оптимизация и расширение WordPress, включая фильтры и улучшения запросов;
- ABC Pagination — удобная пагинация для фильтрованных результатов;
- Плагины для AJAX-фильтрации, поддерживающие интеграцию с кастомными запросами.
Использование готовых решений экономит время и снижает риск ошибок, но глубокое понимание кода и запросов всегда полезно.
Оптимизация запросов и советы по производительности
При сложных фильтрах нужно помнить, что WP_Query с большим количеством условий может грузить сервер. Советы:
- Индексируйте метаполя в базе данных, если часто фильтруете по ним;
- Используйте transient API или кэширование результатов фильтра для ускорения;
- Пагинация обязательна, не выводите слишком много записей за раз;
- Оптимизируйте количество и тип JOIN в запросах, чтобы избежать лишних нагрузок.
Если сайт большой, имеет смысл рассмотреть специализированные решения вроде ElasticSearch или плагинов с внешним поиском.