В современных проектах WordPress часто возникает задача показать пользователю удобный, динамический список постов, который можно фильтровать по категориям, меткам, таксономиям и другим параметрам без перезагрузки страницы. В этой статье мы подробно разберём, как создать такой фильтрованный список постов с использованием WP_Query и AJAX, а также приведём примеры кода, которые можно адаптировать под свои нужды.
Основы фильтрации постов в WordPress с WP_Query
WP_Query – это класс WordPress, который позволяет формировать запросы к базе данных для получения постов по заданным параметрам. Для фильтрации можно использовать:
- Параметры таксономий (категории, метки и кастомные таксономии)
- Параметры даты, автора, статуса
- Кастомные поля (meta_query)
Пример простого запроса для получения постов из категории с ID 5:
$args = [
'cat' => 5,
'posts_per_page' => 10,
];
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<h2>' . get_the_title() . '</h2>';
}
}
wp_reset_postdata();
Однако этот подход статичен — при изменении фильтра нужно обновлять страницу. Чтобы сделать фильтрацию динамической, подключим AJAX.
Реализация динамической фильтрации через AJAX в WordPress
Для реализации динамической фильтрации нам нужны три шага:
- Создать форму фильтра с элементами управления (селекты, чекбоксы и т.п.)
- Написать JS-код, который будет отправлять AJAX-запрос при изменении фильтров
- Обработчик AJAX на PHP, который выполнит WP_Query с параметрами и вернёт HTML с результатами
1. Форма фильтра
Пример простой формы с двумя фильтрами — категория и метка:
<form id="wpvip-filter-form">
<select name="category" id="wpvip-filter-category">
<option value="">Все категории</option>
<?php
$categories = get_categories();
foreach ($categories as $cat) {
echo '<option value="' . esc_attr($cat->term_id) . '">' . esc_html($cat->name) . '</option>';
}
?>
</select>
<select name="tag" id="wpvip-filter-tag">
<option value="">Все метки</option>
<?php
$tags = get_tags();
foreach ($tags as $tag) {
echo '<option value="' . esc_attr($tag->term_id) . '">' . esc_html($tag->name) . '</option>';
}
?>
</select>
</form>
<div id="wpvip-filter-results"></div>
2. JavaScript для отправки AJAX-запроса
Добавим скрипт, который при изменении фильтров отправляет запрос на сервер и обновляет список постов:
jQuery(document).ready(function($) {
$('#wpvip-filter-form select').on('change', function() {
var data = {
action: 'wpvip_filter_posts',
category: $('#wpvip-filter-category').val(),
tag: $('#wpvip-filter-tag').val()
};
$.ajax({
url: wpvip_ajax.ajax_url,
type: 'POST',
data: data,
beforeSend: function() {
$('#wpvip-filter-results').html('<p>Загрузка...</p>');
},
success: function(response) {
$('#wpvip-filter-results').html(response);
},
error: function() {
$('#wpvip-filter-results').html('<p>Ошибка загрузки данных.</p>');
}
});
});
});
Не забудьте подключить этот скрипт и локализовать объект wpvip_ajax через wp_localize_script в functions.php или вашем плагине:
function wpvip_enqueue_scripts() {
wp_enqueue_script('wpvip-filter-js', get_template_directory_uri() . '/js/wpvip-filter.js', ['jquery'], null, true);
wp_localize_script('wpvip-filter-js', 'wpvip_ajax', [
'ajax_url' => admin_url('admin-ajax.php'),
]);
}
add_action('wp_enqueue_scripts', 'wpvip_enqueue_scripts');
3. PHP-обработчик AJAX запроса
Добавим в functions.php обработчик, который сформирует WP_Query с учётом фильтров и вернёт HTML:
function wpvip_ajax_filter_posts() {
$category = isset($_POST['category']) ? intval($_POST['category']) : 0;
$tag = isset($_POST['tag']) ? intval($_POST['tag']) : 0;
$args = [
'post_type' => 'post',
'posts_per_page' => 10,
];
if ($category) {
$args['cat'] = $category;
}
if ($tag) {
$args['tag_id'] = $tag;
}
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<article><h2>' . get_the_title() . '</h2><p>' . get_the_excerpt() . '</p></article>';
}
} else {
echo '<p>Посты не найдены.</p>';
}
wp_reset_postdata();
wp_die();
}
add_action('wp_ajax_wpvip_filter_posts', 'wpvip_ajax_filter_posts');
add_action('wp_ajax_nopriv_wpvip_filter_posts', 'wpvip_ajax_filter_posts');
Расширение фильтрации: добавление кастомных полей и таксономий
Для более сложной фильтрации можно использовать meta_query и tax_query в WP_Query. Например, фильтрация по кастомному полю price и таксономии product_type:
$args = [
'post_type' => 'product',
'meta_query' => [
[
'key' => 'price',
'value' => 1000,
'compare' => '<=',
'type' => 'NUMERIC'
]
],
'tax_query' => [
[
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => 'electronics'
]
]
];
$query = new WP_Query($args);
Такой подход позволит вашим пользователям быстро находить нужные записи с учётом любых параметров.
Практические советы и рекомендации
Чтобы динамический фильтр работал эффективно и без ошибок, учитывайте следующие моменты:
- Всегда валидируйте и экранируйте данные, полученные через AJAX.
- Используйте кэширование результатов, если фильтров много и запросы тяжёлые.
- Оптимизируйте запросы: не запрашивайте лишние поля, используйте
fieldsдля выборки только необходимых данных. - Добавляйте индексы в базу для кастомных полей, если фильтрация по ним часто используется.
Полезные плагины для расширения функционала фильтрации
Если не хочется писать код с нуля, можно обратить внимание на плагины:
- Clearfy Pro — оптимизация и улучшение запросов, управление кэшем.
- WPRemark — расширение функционала отзывов и фильтров по ним.
Но написанный вручную код даёт полный контроль и гибкость под любые задачи.