Разное количество записей на первой странице архива
Мне нужно выводить разное количество записей на первой странице архива по сравнению с остальными страницами.
Например, вот что мне нужно:
- Всего записей: 6
- Первая страница: 3 записи
- Последующие страницы: по 2 записи на странице
Вот мой код:
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$fp_limit = 3; // лимит для первой страницы
$limit = 2; // лимит для последующих страниц
$offset = 0; // стандартное смещение
if( $paged == 1 ) {
$limit = $fp_limit;
} else {
$offset = $fp_limit + ( ($paged - 2) * $limit );
}
$args = array(
'post_type' => 'my_post_type',
'post_status' => 'publish',
'offset' => $offset,
'posts_per_page' => $limit,
'caller_get_posts' => -1, // убрать sticky записи
'paged' => $paged,
'tax_query' => array(
array(
'taxonomy' => 'my_taxo',
'field' => 'slug',
'terms' => array('slug1', 'slug2', 'slug3')
)
)
);
$my_query = null;
$my_query = new WP_Query($args);
// стандартный цикл
if( $my_query->have_posts() ) :
while ($my_query->have_posts()) : $my_query->the_post();
...
endwhile; endif; // цикл архива
if (function_exists('wp_pagenavi')){ wp_pagenavi( array( 'query' => $my_query ) ); }
wp_reset_query();
На первой странице архива этот код предполагает:
Всего 6 записей, по 3 записи на странице. Значит нужно 2 страницы архива, и пагинация выглядит так:
[1] [2]
Однако на любой другой странице архива код предполагает:
Всего 6 записей, по 2 записи на странице. Значит нужно 3 страницы архива, и пагинация выглядит так:
[1] [2] [3]
Нужна помощь в исправлении этой проблемы.

РЕДАКТИРОВАНИЕ - ПЕРЕСМОТРЕННЫЙ ОТВЕТ
Я работал над другим решением, которое на самом деле лучше первоначального ответа. Оно не включает кастомные запросы, и я считаю, что первоначальный ответ можно оставить только для ознакомления.
Я по-прежнему предполагаю, что вы находитесь на главной странице и буду рассматривать этот случай именно так. Итак, вот мое новое решение.
ШАГ 1
Удалите кастомный запрос с главной страницы и замените его стандартным циклом.
<?php
if ( have_posts() ) :
// Начало цикла.
while ( have_posts() ) : the_post();
///<---ВАШ ЦИКЛ--->
endwhile;
//<---ВАША ПАГИНАЦИЯ--->
else :
//ЗАПИСИ НЕ НАЙДЕНЫ ИЛИ ЧТО-ТО ДРУГОЕ
endif;
?>
ШАГ 2
Используйте pre_get_posts
, чтобы изменить основной запрос и добавить вашу кастомную таксономию в главный запрос для отображения на главной странице.
ШАГ 3
Теперь получите опцию posts_per_page
, установленную в админке (предполагаю, что это 2), и также установите offset
, который мы будем использовать. Он будет равен 1
, так как вам нужно 3 записи на первой странице и 2 на остальных.
$ppg = get_option('posts_per_page');
$offset = 1;
ШАГ 4
На первой странице вам нужно добавить offset
к posts_per_page
, что в сумме даст 3 записи на первой странице.
$query->set('posts_per_page', $offset + $ppp);
ШАГ 5
Вы должны применить offset
ко всем последующим страницам, иначе получите повторение последней записи текущей страницы на следующей.
$offset = $offset + ( ($query->query_vars['paged']-1) * $ppp );
$query->set('posts_per_page',$ppp);
$query->set('offset',$offset);
ШАГ 6
Наконец, вам нужно вычесть ваш offset из found_posts
, иначе пагинация на последней странице будет работать некорректно и выдаст ошибку 404
из-за неправильного подсчета записей.
ПРИМЕЧАНИЕ: Этот код ломал пагинацию на странице поиска. Теперь это исправлено, см. обновленный код.
function homepage_offset_pagination( $found_posts, $query ) {
$offset = 1;
if( $query->is_home() && $query->is_main_query() ) {
$found_posts = $found_posts - $offset;
}
return $found_posts;
}
add_filter( 'found_posts', 'homepage_offset_pagination', 10, 2 );
ВСЕ ВМЕСТЕ
Вот как будет выглядеть полный запрос, который нужно добавить в functions.php
function tax_and_offset_homepage( $query ) {
if ($query->is_home() && $query->is_main_query() && !is_admin()) {
$query->set( 'post_type', 'my_post_type' );
$query->set( 'post_status', 'publish' );
$query->set( 'ignore_sticky_posts', '-1' );
$tax_query = array(
array(
'taxonomy' => 'my_taxo',
'field' => 'slug',
'terms' => array('slug1', 'slug2', 'slug3')
)
);
$query->set( 'tax_query', $tax_query );
$ppp = get_option('posts_per_page');
$offset = 1;
if (!$query->is_paged()) {
$query->set('posts_per_page',$offset + $ppp);
} else {
$offset = $offset + ( ($query->query_vars['paged']-1) * $ppp );
$query->set('posts_per_page',$ppp);
$query->set('offset',$offset);
}
}
}
add_action('pre_get_posts','tax_and_offset_homepage');
function homepage_offset_pagination( $found_posts, $query ) {
$offset = 1;
if( $query->is_home() && $query->is_main_query() ) {
$found_posts = $found_posts - $offset;
}
return $found_posts;
}
add_filter( 'found_posts', 'homepage_offset_pagination', 10, 2 );

Я знаю, что это из каменного века, но вот еще одно решение для тех, кто ищет способ сделать это с помощью пользовательского запроса. В этом примере на первой странице нужно 10 записей, а на каждой последующей — 9.
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
if( $paged == 1 ) {
$limit = 10; // Первая страница — 10 постов
} else {
$limit = 9; // Остальные страницы — по 9 постов
}
Затем в массиве аргументов используйте:
'posts_per_page' => $limit,
Теперь всё готово.

Это не сработает. При таком подходе пост №10 будет отображаться дважды. При переходе на вторую страницу система "подумает", что на первой странице также было отображено 9 постов, и поэтому начнет показывать пост №10 снова, хотя он уже был отображен на первой странице.

Киль был очень близок к решению. Мне нужно было 3 поста на главной странице и 12 на последующих, вот к чему я пришёл:
<?php
$paged = ( get_query_var( 'paged' ) ) ? absint( get_query_var( 'paged' ) ) : 1;
$current_cat = get_category($cat);
$limit = 12; // Лимит постов на всех страницах, кроме первой
$offset = 3; // Устанавливаем смещение равным количеству постов на первой странице
if( $paged == 1 ) {
$offset = 0; // На первой странице смещение не нужно
$limit = 3; // Количество постов на главной
} else {
$offset = (($paged - 2) * $limit) + $offset; // Здесь происходит магия
}
$args = array(
'post_type' => 'post',
'category_name' => $current_cat->slug,
'paged' => $paged,
'offset' => $offset,
'posts_per_page' => $limit,
'orderby' => 'date',
'order' => 'DESC',
);
?>
