Разное количество записей на первой странице архива

25 июл. 2014 г., 12:40:37
Просмотры: 15.2K
Голосов: 16

Мне нужно выводить разное количество записей на первой странице архива по сравнению с остальными страницами.

Например, вот что мне нужно:

  • Всего записей: 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]

Нужна помощь в исправлении этой проблемы.

7
Комментарии

Если бы я только мог указать WP_pagenavi, сколько постов показывать на первой странице, а сколько на остальных...

norixxx norixxx
25 июл. 2014 г. 12:59:43

Почему именно так нужно сделать? Есть какая-то особая причина?

Pieter Goosen Pieter Goosen
25 июл. 2014 г. 13:06:32

Просто прихоть моего клиента. Мне на самом деле все равно, использовать wp_pagenavi или нет. Есть ли другие методы, которые я могу использовать?

norixxx norixxx
25 июл. 2014 г. 13:12:53

Во-первых, 'caller_ get_ posts' содержит пробелы и не является валидным. Во-вторых, этот параметр устарел. Вместо него используйте ignore_sticky_posts.

kaiser kaiser
25 июл. 2014 г. 15:22:21

Ваша главная страница — это обычная домашняя страница или она установлена как фронт-страница?

Pieter Goosen Pieter Goosen
25 июл. 2014 г. 15:48:46

Я не знал, что caller_get_posts устарел...

norixxx norixxx
26 июл. 2014 г. 02:50:10

При разработке следует включать режим отладки (debug). В этом режиме вы бы увидели данное сообщение

Pieter Goosen Pieter Goosen
26 июл. 2014 г. 07:45:14
Показать остальные 2 комментариев
Все ответы на вопрос 3
1
25

РЕДАКТИРОВАНИЕ - ПЕРЕСМОТРЕННЫЙ ОТВЕТ

Я работал над другим решением, которое на самом деле лучше первоначального ответа. Оно не включает кастомные запросы, и я считаю, что первоначальный ответ можно оставить только для ознакомления.

Я по-прежнему предполагаю, что вы находитесь на главной странице и буду рассматривать этот случай именно так. Итак, вот мое новое решение.

ШАГ 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 );
25 июл. 2014 г. 17:11:06
Комментарии

Другой способ — избегать использования offset и применять 'post__not_in', исключая первую запись из запросов на страницах, отличных от 0.

Luca Reghellin Luca Reghellin
4 дек. 2020 г. 19:10:32
1

Я знаю, что это из каменного века, но вот еще одно решение для тех, кто ищет способ сделать это с помощью пользовательского запроса. В этом примере на первой странице нужно 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,

Теперь всё готово.

21 февр. 2018 г. 12:57:39
Комментарии

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

norman.lol norman.lol
9 мая 2019 г. 09:24:56
0

Киль был очень близок к решению. Мне нужно было 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',
);
?>
12 апр. 2022 г. 21:38:00