Динамические списки постов с фильтрами — частая задача при разработке сайтов на WordPress. Они позволяют пользователям быстро находить нужный контент без перезагрузки страницы. В этой статье подробно разберём, как создать такой список с использованием AJAX и PHP, рассмотрим примеры кода и оптимизации.
Зачем использовать AJAX для фильтрации постов в WordPress
Стандартная фильтрация постов на WP подразумевает перезагрузку страницы при смене параметров. Это неудобно и влияет на UX. AJAX позволяет отправлять запросы на сервер асинхронно, обновляя контент на странице без перезагрузки, что ускоряет взаимодействие пользователя с сайтом.
Кроме этого, AJAX-фильтры снижают нагрузку на сервер и уменьшают трафик, так как отправляются только необходимые данные, а не весь HTML страницы.
Для реализации потребуется написать PHP-функцию, которая будет обрабатывать AJAX-запросы, и JavaScript-код, который будет отправлять запросы и обновлять список постов на странице.
Создание PHP-функции для обработки AJAX-запроса
Начнём с добавления функции в файл functions.php вашей темы или в свой плагин. Эта функция будет получать параметры фильтра из запроса, формировать WP_Query и возвращать HTML с отфильтрованными постами.
function wppuzzle_get_filtered_posts() {
// Проверяем nonce для безопасности
check_ajax_referer('wppuzzle_filter_nonce', 'nonce');
$category = isset($_POST['category']) ? sanitize_text_field($_POST['category']) : '';
$posts_per_page = 5;
$args = [
'post_type' => 'post',
'posts_per_page' => $posts_per_page,
];
if ($category) {
$args['category_name'] = $category;
}
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<div class="wppuzzle-post-item">';
echo '<h3><a href="'.get_permalink().'">'.get_the_title().'</a></h3>';
echo '<p>'.get_the_excerpt().'</p>';
echo '</div>';
}
} else {
echo '<p>Посты не найдены.</p>';
}
wp_die();
}
add_action('wp_ajax_wppuzzle_filter_posts', 'wppuzzle_get_filtered_posts');
add_action('wp_ajax_nopriv_wppuzzle_filter_posts', 'wppuzzle_get_filtered_posts');Здесь мы создаём WP_Query с параметром категории, если он передан, и выводим заголовок и краткое описание поста.
JavaScript для отправки AJAX-запроса и обновления контента
Теперь добавим JS-код, который будет реагировать на изменение фильтра и отправлять AJAX-запрос.
jQuery(document).ready(function($){
$('#wppuzzle-category-filter').on('change', function(){
var category = $(this).val();
$.ajax({
url: wppuzzle_ajax_object.ajax_url,
type: 'POST',
data: {
action: 'wppuzzle_filter_posts',
category: category,
nonce: wppuzzle_ajax_object.nonce
},
beforeSend: function() {
$('#wppuzzle-post-list').html('<p>Загрузка...</p>');
},
success: function(data) {
$('#wppuzzle-post-list').html(data);
},
error: function() {
$('#wppuzzle-post-list').html('<p>Произошла ошибка, попробуйте позже.</p>');
}
});
});
});Этот скрипт слушает изменение select с id wppuzzle-category-filter и отправляет выбранное значение на сервер. Затем обновляет блок с постами.
Подключение скрипта и локализация переменных
Чтобы JS-запрос знал URL для AJAX и nonce, добавим в PHP код для подключения скрипта и передачи данных:
function wppuzzle_enqueue_scripts() {
wp_enqueue_script('wppuzzle-filter', get_template_directory_uri() . '/js/wppuzzle-filter.js', ['jquery'], null, true);
wp_localize_script('wppuzzle-filter', 'wppuzzle_ajax_object', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('wppuzzle_filter_nonce')
]);
}
add_action('wp_enqueue_scripts', 'wppuzzle_enqueue_scripts');Не забудьте создать файл wppuzzle-filter.js в папке js вашей темы и вставить туда JS-код.
HTML-разметка фильтра и контейнера для постов
В шаблоне страницы или в нужном месте добавьте простой фильтр и блок для вывода постов:
<select id="wppuzzle-category-filter">
<option value="">Все категории</option>
<option value="novosti">Новости</option>
<option value="stati">Статьи</option>
</select>
<div id="wppuzzle-post-list">
<!-- Здесь будет список постов -->
</div>Можно динамически вывести категории через wp_list_categories() или вручную, если категорий немного.
Советы по оптимизации и расширению функционала
1. Добавьте пагинацию с подгрузкой следующей страницы через AJAX, чтобы не загружать сразу много постов.
2. Используйте транзиенты или объектный кеш для кеширования результата WP_Query, чтобы снизить нагрузку на базу.
3. Расширьте фильтр дополнительными параметрами — тегами, датами публикации, пользовательскими полями.
4. Внедрите обработку ошибок и уведомления об отсутствии результатов для лучшего UX.
5. Для визуальной части применяйте анимации загрузки и плавное появление новых постов.
Пример расширения фильтра по дате публикации
Добавим фильтр по году публикации. Для этого расширим JS и PHP код.
В HTML добавьте ещё один селект:
<select id="wppuzzle-year-filter">
<option value="">Все годы</option>
<option value="2024">2024</option>
<option value="2023">2023</option>
</select>В JS измените обработчик, чтобы учитывать оба фильтра:
$('#wppuzzle-category-filter, #wppuzzle-year-filter').on('change', function(){
var category = $('#wppuzzle-category-filter').val();
var year = $('#wppuzzle-year-filter').val();
$.ajax({
url: wppuzzle_ajax_object.ajax_url,
type: 'POST',
data: {
action: 'wppuzzle_filter_posts',
category: category,
year: year,
nonce: wppuzzle_ajax_object.nonce
},
beforeSend: function() {
$('#wppuzzle-post-list').html('<p>Загрузка...</p>');
},
success: function(data) {
$('#wppuzzle-post-list').html(data);
},
error: function() {
$('#wppuzzle-post-list').html('<p>Произошла ошибка, попробуйте позже.</p>');
}
});
});В PHP добавьте обработку года:
function wppuzzle_get_filtered_posts() {
check_ajax_referer('wppuzzle_filter_nonce', 'nonce');
$category = isset($_POST['category']) ? sanitize_text_field($_POST['category']) : '';
$year = isset($_POST['year']) ? intval($_POST['year']) : 0;
$args = [
'post_type' => 'post',
'posts_per_page' => 5,
];
if ($category) {
$args['category_name'] = $category;
}
if ($year) {
$args['year'] = $year;
}
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
echo '<div class="wppuzzle-post-item">';
echo '<h3><a href="'.get_permalink().'">'.get_the_title().'</a></h3>';
echo '<p>'.get_the_excerpt().'</p>';
echo '</div>';
}
} else {
echo '<p>Посты не найдены.</p>';
}
wp_die();
}Заключение
Создание динамического списка постов с фильтрацией на AJAX в WordPress — отличный способ улучшить удобство сайта и сделать интерфейс более отзывчивым. В статье рассмотрен базовый пример с фильтрацией по категории и году, который можно расширять под любые задачи.
Для быстрого старта можно использовать плагины, например, ABC Pagination для удобной пагинации, или Clearfy Pro для оптимизации работы сайта.