Диагностика проблемы: почему пагинация с несколькими WP_Query не работает
Когда на одной странице WordPress выводится несколько запросов WP_Query, часто возникает проблема с пагинацией. Обычно параметр paged работает корректно с единственным запросом, но при нескольких – переход по страницам приводит к сбоям, например, отображается одинаковый набор записей, или при клике на страницу пагинации возникает ошибка 404.
Причина кроется в том, что WordPress использует глобальный параметр paged для текущей страницы, но при нескольких запросах нужно грамотно передавать и обрабатывать разные параметры пагинации для каждого из них. Без дополнительной обработки WP_Query не понимает, какой именно номер страницы нужно вывести.
Пошаговое решение: как правильно настроить пагинацию с несколькими WP_Query
1. Получаем параметр paged из URL с разными именами
Чтобы различать пагинацию для каждого запроса, создайте разные параметры, например, paged1 и paged2 в URL. Например: ?paged1=2&paged2=1.
$paged1 = (get_query_var('paged1')) ? intval(get_query_var('paged1')) : 1;
$paged2 = (get_query_var('paged2')) ? intval(get_query_var('paged2')) : 1;
Если вы используете $_GET, то так:
$paged1 = isset($_GET['paged1']) ? intval($_GET['paged1']) : 1;
$paged2 = isset($_GET['paged2']) ? intval($_GET['paged2']) : 1;
2. Создаем кастомные WP_Query с передачей соответствующего paged
$args1 = [
'post_type' => 'post',
'posts_per_page' => 5,
'paged' => $paged1,
];
$query1 = new WP_Query($args1);
$args2 = [
'post_type' => 'product',
'posts_per_page' => 5,
'paged' => $paged2,
];
$query2 = new WP_Query($args2);
3. Выводим результаты и добавляем пагинацию с разными параметрами
Для каждого запроса используйте собственный навигатор пагинации, который формирует ссылки с нужным параметром:
function custom_pagination($query, $paged_param) {
$big = 999999999; // число для замены
echo paginate_links([
'base' => str_replace($big, '%#%', esc_url(add_query_arg($paged_param, $big))),
'format' => '',
'current' => max(1, $query->get('paged')),
'total' => $query->max_num_pages,
'add_args' => false,
]);
}
// В шаблоне вывода
if ($query1->have_posts()) {
while ($query1->have_posts()) {
$query1->the_post();
the_title('<h3>', '</h3>');
}
custom_pagination($query1, 'paged1');
}
wp_reset_postdata();
if ($query2->have_posts()) {
while ($query2->have_posts()) {
$query2->the_post();
the_title('<h3>', '</h3>');
}
custom_pagination($query2, 'paged2');
}
wp_reset_postdata();
Проверка результата после внедрения
- Откройте страницу с двумя списками постов и убедитесь, что при переходе по страницам у каждого списка меняется контент отдельно.
- Проверьте ссылки пагинации – они должны содержать соответствующие параметры (
?paged1=2или?paged2=3). - Ошибки 404 при переходе на страницы пагинации отсутствуют.
- Проверьте работоспособность в разных браузерах и на мобильных устройствах.
Частые ошибки и как их исправить
- Использование одного параметра paged для всех запросов: приводит к конфликтам и одинаковой пагинации всех списков. Решение – использовать разные GET-параметры.
- Отсутствие сброса данных после цикла (
wp_reset_postdata()): может привести к неправильному выводу данных. Обязательно вызывайте функцию после каждого запроса. - Неправильная генерация ссылок пагинации: используйте
paginate_linksс корректным параметромbaseиadd_args, чтобы сохранять другие параметры URL. - Прямое использование
get_query_var('paged')без проверки: если параметр в URL отсутствует, значение будет пустым, что может привести к ошибкам. Всегда устанавливайте значение по умолчанию.
Практические советы по безопасности и производительности
- При использовании GET-параметров пагинации всегда приводите их к целочисленному типу с помощью
intval(), чтобы предотвратить XSS и SQL-инъекции. - Кешируйте результаты запросов WP_Query с помощью Transients API или Object Cache, если данные не меняются часто, чтобы снизить нагрузку на БД.
- Не выводите слишком много постов на страницу, особенно с несколькими запросами, чтобы избежать проблем с производительностью.
- Используйте
pre_get_posts, если хотите глобально изменить параметры пагинации для основных запросов, но для нескольких запросов на странице лучше использовать отдельные WP_Query.
Сравнение вариантов реализации пагинации с несколькими WP_Query
| Вариант | Плюсы | Минусы |
|---|---|---|
Один параметр paged для всех запросов | Простота реализации | Пагинация конфликтует, невозможно использовать несколько списков |
Разные GET-параметры (paged1, paged2) | Гибкость, независимая пагинация для каждого запроса | Сложнее URL, нужно дополнительное управление параметрами |
| AJAX пагинация для каждого запроса | Плавный пользовательский опыт, динамическая загрузка | Требует дополнительного JS, сложнее в реализации и поддержке |