Have different number of posts on first page

I need to have a different amount of posts per page on the first page that on the other pages.

For example, this is what I need

  • Total posts: 6
  • First page: showing 3 posts
  • Following page: showing 2 posts per page

Here’s my code:

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

$fp_limit = 3; // first page limit
$limit = 2; // following page limit
$offset = 0; // default offset

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, // remove sticky post
    '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);

// basic loop
if( $my_query->have_posts() ) : 
while ($my_query->have_posts()) : $my_query->the_post();

...

endwhile; endif; // archive loop
if (function_exists('wp_pagenavi')){ wp_pagenavi( array( 'query' => $my_query ) ); }

wp_reset_query();

At first page in archive, this code assumes:

Well, 6 posts total and 3 posts per page. So I need 2 archive pages and the pagination I present to you is:

[1] [2]

However, any other page in archive the code assumes:

Well, 6 posts total and 2 posts per page. So I need 3 archive pages and the pagination I present to you is:

[1] [2] [3]

Need a little help to fix this.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

EDIT – ANSWER REVISITED

I’ve being working on another solution which is actually better the original answer. This does not involve any custom query and I think for all purposes my original answer can be dropped but kept for informational purposes

I still believe you are on the homepage and will also treat this as such. So this is my new solution

STEP 1

Remove the custom query from the homepage and replace it with the default loop

<?php

        if ( have_posts() ) :
            // Start the Loop.
            while ( have_posts() ) : the_post();

                ///<---YOUR LOOP--->

            endwhile;

                //<---YOUR PAGINATION--->   

            else : 

                //NO POSTS FOUND OR SOMETHING   

            endif; 

    ?>

STEP 2

Use pre_get_posts to alter the main query to add your custom taxonomy to the main query to display on the home page.

STEP 3

Now, get the posts_per_page option set from the back end (which I assume is 2) and also set your offset which we are going to use. That will be 1 as you will need 3 posts on page one and 2 on the rest

$ppg = get_option('posts_per_page');
$offset = 1;

STEP 4

On page one, you’ll need to add the offset to posts_per_page will add up to 3 to get your three posts on page one.

$query->set('posts_per_page', $offset + $ppp);

STEP 5

You must apply your offset to all subsequent pages, otherwise you will get a repetition of the last post of the page on the next page

$offset = $offset + ( ($query->query_vars['paged']-1) * $ppp );
$query->set('posts_per_page',$ppp);
$query->set('offset',$offset);

STEP 6

Lastly, you need to subtract your offset from found_posts otherwise your pagination on the last page will be wrong and give you a 404 error as the last post will be missing due to the incorrect post count

NOTE: This piece of code broke pagination on the search page. This is now fixed, see the updated code

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 );

ALL TOGETHER

This is how your complete query will look like that should go into 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 );

Method 2

I know this is from 1000 years ago, but another solution for anyone else looking for this solution while using a custom query, here is how to do it. In this example the 1st page needed 10 posts and every subsequent page needs 9.

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
if( $paged == 1 ) {
   $limit = 10;
} else {
   $limit = 9;
}

and then in the array use this:

'posts_per_page' => $limit,

Now you’re good to go.

Method 3

Kiel was really close. I needed 3 on the front page, 12 on subsequent pages, this is where I landed:

<?php 
$paged = ( get_query_var( 'paged' ) ) ? absint( get_query_var( 'paged' ) ) : 1;
$current_cat = get_category($cat);

$limit = 12; // Set the posts limit on all the pages but the first
$offset = 3; // Set this to the number of posts on the first page

if( $paged == 1 ) {
   $offset = 0; // No offset on the first page
   $limit = 3; // Number of posts on the front
} else {
   $offset = (($paged - 2) * $limit) + $offset; // The magic happens here
}

$args = array(
    'post_type' => 'post',
    'category_name' => $current_cat->slug,
    'paged' => $paged,
    'offset' => $offset,
    'posts_per_page' => $limit,
    'orderby' => 'date',
    'order' => 'DESC',
);
?>


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x