Диагностика проблемы: почему пагинация ломается при комбинировании WP_Query и pre_get_posts
Часто разработчики сталкиваются с проблемой, когда пагинация не работает корректно на страницах, где одновременно используется кастомный запрос WP_Query и изменяется главный запрос с помощью хука pre_get_posts. В результате при переходе по страницам пагинации появляются ошибки 404 или повторяется первая страница. Основная причина — конфликт параметров запроса и неправильная обработка параметра paged.
Чтобы понять, где именно возникает проблема, необходимо проверить следующие моменты:
- Передается ли параметр
pagedв оба запроса. - Не перезаписывается ли глобальный объект
$wp_queryнекорректно. - Правильно ли реализована пагинация в разметке — используются ли правильные ссылки с учетом пагинации.
Пошаговое решение проблемы
1. Правильная установка параметра paged
Параметр paged должен быть получен из глобальной переменной запроса и передан в оба запроса (если оба требуют пагинации). Пример получения:
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;2. Использование pre_get_posts для изменения главного запроса
Если вы изменяете главный запрос через pre_get_posts, убедитесь, что не создаете дополнительный WP_Query без необходимости. Пример правильной реализации:
add_action('pre_get_posts', function($query) {
if ( !is_admin() && $query->is_main_query() && is_post_type_archive('product') ) {
$query->set('posts_per_page', 10);
// Параметр paged не нужно устанавливать вручную здесь — WP сам его подхватит
}
});3. Если нужен дополнительный кастомный запрос WP_Query
При создании второго запроса на той же странице важно явно передать параметр paged:
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$args = [
'post_type' => 'custom_post',
'posts_per_page' => 5,
'paged' => $paged
];
$custom_query = new WP_Query($args);При этом пагинация для кастомного запроса должна строиться на основе $custom_query->max_num_pages.
Проверка результата после внедрения
- Перейдите на страницу с пагинацией и убедитесь, что при переходе на вторую и последующие страницы URL меняется корректно (например,
/page/2/). - Проверьте, что на каждой странице показывается правильный набор постов.
- Отсутствуют ли ошибки 404 при переходе по страницам.
- Включите
WP_DEBUGи проверьте, нет ли предупреждений о неправильных запросах.
Частые ошибки и их исправление
- Ошибка: Параметр
pagedне передается в кастомный WP_Query.
Исправление: Явно добавьте'paged' => $pagedв аргументы запроса. - Ошибка: Несоответствие пагинации при использовании нескольких WP_Query.
Исправление: Используйте разные переменные для каждого запроса и правильно формируйте ссылки пагинации черезpaginate_links()с параметром'current'. - Ошибка: Изменение параметров главного запроса в
pre_get_postsбез проверки$query->is_main_query().
Исправление: Всегда добавляйте проверкуif ($query->is_main_query()), чтобы избежать побочных эффектов.
Практические советы по безопасности и производительности
- Избегайте выполнения сложных кастомных запросов на странице с пагинацией, если можно изменить главный запрос через
pre_get_posts. - Кэшируйте результаты запросов, если данные не меняются часто, чтобы снизить нагрузку на базу данных.
- Проверяйте входящие параметры
pagedна валидность (целое число, больше 0), чтобы предотвратить SQL-инъекции или ошибки. - При построении ссылок пагинации используйте стандартные функции WordPress (
paginate_links(),get_pagenum_link()) для корректной генерации URL.
Сравнение способов реализации пагинации с кастомными запросами
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
Изменение главного запроса через pre_get_posts | Перехват и модификация главного запроса WordPress | Легко интегрируется, меньше кода, SEO-дружелюбно | Ограничено одним запросом на страницу |
| Использование дополнительного WP_Query | Создание отдельного кастомного запроса для вывода данных | Гибкость, можно использовать несколько запросов | Нужна ручная обработка пагинации, выше нагрузка |
| AJAX пагинация с WP_Query | Загрузка постов без перезагрузки страницы | Улучшенный UX, уменьшение нагрузки на сервер | Сложнее в реализации, требует JS и правильного кеширования |