Custom posts per page does not work with pagination

I have one page in my template where I would like to set a custom posts_per_page.
Here is the code I have used:

<?php
global $query_string;
query_posts($query_string . '&posts_per_page=4'); 
if ( have_posts() ) : while ( have_posts() ) : the_post();
...

Now this code limits only 4 items per page and shows pageinate_links below as I have written. However clicking on any other page will lead to a 404.

Read More

If I take out the global and query_posts line then it works fine.

This is the paginate_links function I am using:

echo paginate_links( array(
    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
    'format' => '?paged=%#%',
    'current' => max( 1, get_query_var('paged') ),
    'total' => $wp_query->max_num_pages,
    'prev_text' => 'Previous',
    'next_text' => 'Next',  
) );

Related posts

Leave a Reply

2 comments

  1. Use a pre_get_posts action in your functions.php with conditional tags, and remove the call to query_posts:

    function wpa62751_pre_get_posts( $query ) {
        if ( is_category( 'my-category' ) && is_main_query() )
            $query->set( 'posts_per_page', 4 );
    }
    add_action( 'pre_get_posts', 'wpa62751_pre_get_posts' );
    
  2. Note – The recommended way is pointed out by @Milo, Use of pre_get_post is always a good choice over query_posts

    However, you can make it work with pagination by passing paged parameter.

    Example –

    global $wp_query;
    $args = array_merge( 
                    $wp_query->query, // old query
                    array( 
                        'posts_per_page' => 4,
                        'paged' => get_query_var('paged')
                        //  'paged' => get_query_var('page')
                    ) 
            );  
    query_posts( $args );