4

I have a filter using pre_get_posts to change the number of posts per page from 4 on the news landing page to 8 on all other pages (page 2, 3, etc). However I don't seem to have got the offset correct, or something, because my get_next_posts_page_link doesn't show a page 3, even though it does exist if I go to the url manually. The current offset is something I somehow managed to conjure up accidentally, I thought it worked as page 2 was correct but as I added more test posts, I realised it didn't work.

function page_2_posts_per_page_filter( $query ) {

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

    if ( !is_admin() && $query->is_paged && $query->is_main_query() ) {

        $offset = 4 + (($paged - 2) * 8);
        $query->set( 'offset', $offset );
        $query->set( 'posts_per_page', 8 );

    } else if (!is_admin() && $query->is_main_query()) {

        $query->set( 'posts_per_page', 4 );

    }
    return;
}
add_action( 'pre_get_posts', 'page_2_posts_per_page_filter', 1 );

EDIT: SOLUTION

function page_2_posts_per_page_filter( $query ) {

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

    if ( !is_admin() && $query->is_paged && $query->is_main_query() ) {

        $offset = (($paged - 1) * 8) - $offset;
        $query->set( 'posts_per_page', 8 );
        $query->set( 'offset', $offset );

    } else if (!is_admin() && $query->is_main_query()) {

        $query->set( 'posts_per_page', 4 );

    }
    return;
}
add_action( 'pre_get_posts', 'page_2_posts_per_page_filter');

function found_offset( $found_posts, $query ) {

    $offset = 4;

    if( !is_admin() && $query->is_main_query() ) {
        $found_posts = $found_posts + $offset;
    }
    return $found_posts;
}
add_action( 'found_posts', 'found_offset', 10, 2 );

1 Answer 1

5

Here is an answer I recently did on another question, the same as your. Because the answer was never upvoted or accepted, I could not mark this question as duplicate, so I have deleted the answer in the other post and reposting it here.

Please note, some points are not aimed at this issue and can be ignored, also, you will just need to make a few alterations on the values as I have not changed anything in the original post. So don't be alarmed by some of the info in the answer ;-)

REPURPOSED ANSWER

Here is a slight variation of an answer I have done on about the same scenario. What differs here is that you want less posts_per_page on page one

STEP 1

Remove query_posts. You should never ever use query_posts

Note: This function isn't meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination).

Replace it with the default loop

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

    <?php if ( 'regularproducts' == get_post_type()  ) : ?>

        //CONTENT HERE

    <?php endif; ?>

    <?php if ( 'wpsc-product' == get_post_type()  ) : ?>

        //CONTENT HERE

    <?php endif; ?>

<?php endwhile; endif; ?>

STEP 2

Use pre_get_posts to alter the main query to add your custom post_types 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 should be set to 300) and also set your offset which we are going to use. That will be 200 as you will need 100 posts on page one and 300 on the rest.

If you don't want to alter the posts_per_page option, you can then just simply set the variable $ppg to 300

$ppg = get_option( 'posts_per_page' );
//$ppg = 300;
$offset = 200;

STEP 4

On page one, you'll need to subtract the offset to posts_per_page

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

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 = ( ( $query->query_vars['paged']-1 ) * $ppp ) - $offset;
$query->set( 'posts_per_page', $ppp );
$query->set( 'offset', $offset ); 

STEP 6

Lastly, you need to add your offset to found_posts otherwise your pagination will will not show the last page

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 = 200;

    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 ( !is_admin() && $query->is_home() && $query->is_main_query() ) {
    $query->set( 'post_type', array( 'regularproducts', 'wpsc-product' ) );

    $ppp = get_option( 'posts_per_page' );
//$ppp = 300;
    $offset = 200;
    if ( !$query->is_paged() ) {
      $query->set( 'posts_per_page', $ppp - $offset );
    } else {
      $offset = ( ( $query->query_vars['paged']-1 ) * $ppp ) - $offset;
      $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 = 200;

    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 );
2
  • You again :) That's brilliant mate, seem to have figured it out from that. Makes total sense to add the offset to the initial amount of posts found. Much appreciated, thank you!
    – evu
    Commented Jun 25, 2015 at 8:42
  • My pleasure. Glad it made sense. ;-) . Enjoy Commented Jun 25, 2015 at 8:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.