Пагинация в WordPress делит список записей на страницы и выводит ссылки с номерами. Для стандартного блога и архивов достаточно the_posts_pagination(). Для отдельного WP_Query используют paginate_links().
Разберём оба варианта и причины, по которым вторая страница возвращает 404 или повторяет первую.
1. Номера страниц в основном цикле WordPress
В index.php, home.php или archive.php после цикла:
<?php
the_posts_pagination( array(
'mid_size' => 1,
'prev_text' => 'Назад',
'next_text' => 'Вперёд',
'screen_reader_text' => 'Навигация по страницам',
'aria_label' => 'Страницы записей',
) );
?>
Функция выводит <nav class="navigation pagination"> с номерами страниц. Текущая страница получает aria-current="page", а mid_size задаёт, сколько номеров показывать по бокам от текущей. Если страница всего одна, ничего не выводится.
Число записей на странице берётся из «Настройки → Чтение → На страницах блога отображать не более». Для простых ссылок «Новее / Старее» без номеров есть the_posts_navigation().
2. Число записей на странице через pre_get_posts
Не заменяй основной цикл архива своим WP_Query только ради другого количества записей. WordPress определяет существование страницы ещё до загрузки шаблона.
Если основной запрос насчитал две страницы, а твой — три, адрес /page/3/ может вернуть 404. Число записей в основном запросе меняй через pre_get_posts.
Правильный способ — изменить основной запрос до его выполнения:
function mytheme_archive_query( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( $query->is_category() ) {
$query->set( 'posts_per_page', 12 );
}
if ( $query->is_home() ) {
$query->set( 'ignore_sticky_posts', true );
}
}
add_action( 'pre_get_posts', 'mytheme_archive_query' );
Проверка is_main_query() ограничивает изменение основным запросом. Условие ! is_admin() исключает административные экраны. В шаблоне остаются обычный цикл и the_posts_pagination().
3. Пагинация отдельного WP_Query
Отдельный запрос нужен для дополнительного списка в шаблоне страницы — например, новостей на странице услуг. Передай ему текущий номер страницы, а общее число страниц возьми из результата этого же запроса:
<?php
$paged = max( 1, get_query_var( 'paged' ), get_query_var( 'page' ) );
$news = new WP_Query( array(
'post_type' => 'post',
'category_name' => 'news',
'posts_per_page' => 6,
'paged' => $paged,
) );
if ( $news->have_posts() ) :
while ( $news->have_posts() ) :
$news->the_post();
get_template_part( 'template-parts/card' );
endwhile;
$links = paginate_links( array(
'total' => $news->max_num_pages,
'current' => $paged,
'mid_size' => 1,
'prev_text' => 'Назад',
'next_text' => 'Вперёд',
) );
if ( $links ) {
echo '<nav class="pagination" aria-label="Страницы новостей"><div class="nav-links">' . $links . '</div></nav>';
}
wp_reset_postdata();
endif;
?>
- На обычных страницах номер приходит в
paged, а на статической главной — вpage.max()учитывает оба случая. totalберётся из твоего запроса, а не из глобального$wp_query— иначе ссылок будет не столько, сколько нужно.paginate_links()сама строит адреса вида/news/page/2/на основе текущей ссылки.wp_reset_postdata()возвращает глобальную запись страницы после своего цикла.
CSS для номеров страниц
.pagination .nav-links {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.pagination .page-numbers {
display: inline-grid;
place-items: center;
min-width: 44px;
min-height: 44px;
padding: 0 12px;
border: 1px solid #d1d5db;
border-radius: 8px;
text-decoration: none;
}
.pagination .page-numbers.current {
background: #1f2937;
border-color: #1f2937;
color: #fff;
}
.pagination .page-numbers.dots {
border-color: transparent;
}
Обёртка .nav-links одинакова у the_posts_pagination() и у своего вывода, поэтому стили общие. Номера по 44 пикселя удобно нажимать пальцем. Многоточие получает класс dots и не является ссылкой.
Почему пагинация не работает: 404 и повторы
- Свой запрос заменяет основной в архиве — перенеси изменения в
pre_get_posts. - Ярлык страницы совпадает с ярлыком рубрики или типа записей, например страница
newsи рубрикаnewsс отключённым префиксом. Переименуй одно из них. - Вторая страница повторяет первую — в запрос не передан
paged. - После изменений в типах записей или структуре ссылок открой «Настройки → Постоянные ссылки» и нажми «Сохранить», чтобы обновить правила.
Если записи выводятся на отдельной странице блога, сначала проверь её настройку — об этом статья о блоге на отдельной странице.