Пагинация — важный элемент навигации для сайтов на WordPress, особенно когда контента много, и его нужно удобно разбить на страницы. В стандартных темах часто встречается простая пагинация, но иногда требуется более сложная, например, многоуровневая пагинация с динамической подгрузкой страниц через AJAX. В этой статье подробно разберем, как создать такую пагинацию, чтобы улучшить пользовательский опыт и снизить нагрузку на сервер.
Что такое многоуровневая пагинация и зачем она нужна
Многоуровневая пагинация — это навигация, которая объединяет несколько видов переключателей страниц, например, классическую нумерацию, кнопки “Следующая”/“Предыдущая”, выбор количества отображаемых элементов и фильтрацию по категориям или тегам. Это удобно для сайтов с разнородным и объемным контентом, например, для блогов, магазинов или каталогов.
Стандартные функции WordPress, такие как paginate_links() или the_posts_pagination(), не поддерживают такой уровень кастомизации, а плагинов с готовой многоуровневой пагинацией не так много. Поэтому придется делать кастомное решение с использованием AJAX.
Подготовка темы и регистрация AJAX-обработчиков
Начнем с регистрации AJAX-обработчиков в файле functions.php вашей темы или в собственном плагине. Это позволит динамически подгружать записи без перезагрузки страницы.
add_action('wp_ajax_wptalk_load_posts', 'wptalk_load_posts_callback');
add_action('wp_ajax_nopriv_wptalk_load_posts', 'wptalk_load_posts_callback');
function wptalk_load_posts_callback() {
$paged = isset($_POST['page']) ? intval($_POST['page']) : 1;
$category = isset($_POST['category']) ? sanitize_text_field($_POST['category']) : '';
$posts_per_page = isset($_POST['posts_per_page']) ? intval($_POST['posts_per_page']) : 5;
$args = [
'post_type' => 'post',
'paged' => $paged,
'posts_per_page' => $posts_per_page
];
if ($category) {
$args['category_name'] = $category;
}
$query = new WP_Query($args);
if ($query->have_posts()) {
ob_start();
while ($query->have_posts()) {
$query->the_post();
?>
<article id="post-<?php the_ID(); ?>">
<h2><?php the_title(); ?></h2>
<div><?php the_excerpt(); ?></div>
</article>
<?php
}
wp_reset_postdata();
$posts_html = ob_get_clean();
wp_send_json_success(['posts' => $posts_html, 'max_page' => $query->max_num_pages]);
} else {
wp_send_json_error('Posts not found');
}
wp_die();
}
Этот обработчик принимает параметры страницы, категории и количества записей, формирует запрос и возвращает HTML постов и максимальное число страниц в формате JSON.
Создание интерфейса пагинации с фильтрами и выбором количества записей
Далее создадим HTML для пагинации с селектами для выбора категории и количества элементов на странице, а также контейнер для постов и навигационные кнопки.
<div id="wptalk-pagination-controls">
<select id="wptalk-category-filter">
<option value="">Все категории</option>
<?php
$categories = get_categories();
foreach ($categories as $cat) {
echo '<option value="' . esc_attr($cat->slug) . '">' . esc_html($cat->name) . '</option>';
}
?>
</select>
<select id="wptalk-posts-per-page">
<option value="5">5 записей</option>
<option value="10">10 записей</option>
<option value="20">20 записей</option>
</select>
</div>
<div id="wptalk-posts-container"></div>
<div id="wptalk-pagination-buttons">
<button id="wptalk-prev-page" disabled>Предыдущая</button>
<span id="wptalk-current-page">1</span> / <span id="wptalk-max-page">1</span>
<button id="wptalk-next-page" disabled>Следующая</button>
</div>
Такой интерфейс позволит пользователю выбирать категорию, количество записей и переключаться между страницами.
JavaScript: загрузка контента и управление пагинацией
Для работы с AJAX добавим скрипт, который будет отправлять запросы на сервер и обновлять содержимое страницы без перезагрузки.
document.addEventListener('DOMContentLoaded', function () {
const postsContainer = document.getElementById('wptalk-posts-container');
const categoryFilter = document.getElementById('wptalk-category-filter');
const postsPerPageSelect = document.getElementById('wptalk-posts-per-page');
const prevBtn = document.getElementById('wptalk-prev-page');
const nextBtn = document.getElementById('wptalk-next-page');
const currentPageSpan = document.getElementById('wptalk-current-page');
const maxPageSpan = document.getElementById('wptalk-max-page');
let currentPage = 1;
let maxPage = 1;
function wptalkLoadPosts() {
const data = new FormData();
data.append('action', 'wptalk_load_posts');
data.append('page', currentPage);
data.append('category', categoryFilter.value);
data.append('posts_per_page', postsPerPageSelect.value);
fetch(wptalk_ajax_object.ajax_url, {
method: 'POST',
credentials: 'same-origin',
body: data
})
.then(response => response.json())
.then(result => {
if (result.success) {
postsContainer.innerHTML = result.data.posts;
maxPage = result.data.max_page;
currentPageSpan.textContent = currentPage;
maxPageSpan.textContent = maxPage;
prevBtn.disabled = currentPage <= 1;
nextBtn.disabled = currentPage >= maxPage;
} else {
postsContainer.innerHTML = '<p>Нет записей для отображения.</p>';
}
})
.catch(() => {
postsContainer.innerHTML = '<p>Произошла ошибка при загрузке.</p>';
});
}
categoryFilter.addEventListener('change', function () {
currentPage = 1;
wptalkLoadPosts();
});
postsPerPageSelect.addEventListener('change', function () {
currentPage = 1;
wptalkLoadPosts();
});
prevBtn.addEventListener('click', function () {
if (currentPage > 1) {
currentPage--;
wptalkLoadPosts();
}
});
nextBtn.addEventListener('click', function () {
if (currentPage < maxPage) {
currentPage++;
wptalkLoadPosts();
}
});
// Инициализация
wptalkLoadPosts();
});
Не забудьте подключить этот скрипт и передать URL AJAX-запроса из PHP:
function wptalk_enqueue_scripts() {
wp_enqueue_script('wptalk-pagination', get_template_directory_uri() . '/js/wptalk-pagination.js', ['jquery'], null, true);
wp_localize_script('wptalk-pagination', 'wptalk_ajax_object', [
'ajax_url' => admin_url('admin-ajax.php')
]);
}
add_action('wp_enqueue_scripts', 'wptalk_enqueue_scripts');
Советы по улучшению и расширению пагинации
Для повышения удобства и производительности можно добавить индикатор загрузки, кэширование запросов на клиенте, а также поддержку бесконечной прокрутки вместо кнопок “Следующая”/“Предыдущая”.
Если вы используете плагин Clearfy Pro, обратите внимание, что он умеет оптимизировать AJAX-запросы и уменьшать нагрузку на базу данных, что может быть полезно при реализации такой пагинации.
Кроме того, для магазинов на WooCommerce возможно расширить пагинацию фильтрами по атрибутам товаров, интегрируя AJAX-запросы с параметрами фильтрации.
Итоги и рекомендации
Создание многоуровневой пагинации с поддержкой AJAX требует базовых знаний о WordPress AJAX API, JavaScript и WP_Query. Наш пример позволяет гибко управлять выводом записей, фильтровать по категориям и менять количество элементов на странице без перезагрузки. Это значительно улучшает UX и производительность сайта.
Для более сложных задач рекомендую рассмотреть кастомные WP REST API эндпоинты и использование популярных JS-фреймворков, например React или Vue, но для большинства проектов приведенное решение будет достаточно.
Если хотите ускорить разработку и получить дополнительные опции оптимизации, обратите внимание на плагины из WPSHOP.ru.