Strange paginate_links behavior. First page link is always whatever page I’m on, all other links are correct

I’m using the following code to generate some pagination:

$wp_query = new WP_Query();
$wp_query->query('posts_per_page=5'.'&paged='.$paged);
$big = 999999999;
echo '<div class="pagination">';
echo paginate_links(array(  'base' => '%_%',
                            'format' => str_replace($big, '%#%', esc_url(get_pagenum_link( $big ))),
                            'current' => max( 1, get_query_var('paged') ),
                            'total' => $wp_query->max_num_pages,
                            'end_size' =>4,
                            'type' => 'list'));     
    echo '</div>';

Its generating my links correctly on the first page, but if I go to any other page everything is still correct except the link for page 1 is always the url of whatever page I am on. Seems like I’m missing somthing simple, anyone know a fix?

Related posts

Leave a Reply

4 comments

  1. Short answer:

    Try

    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
    'format' => '?paged=%#%',
    

    Long answer:

    I took a look at the paginate_links() source code (v3.5.1) and there is this line (#)

    $link = str_replace('%_%', 1 == $n ? '' : $format, $base);
    

    that is giving you the empty first page link.

    With your setup you have $base = "%_%" and $format = "http://example.com/page/%#%/" so this becomes:

    $link = str_replace('%_%', 1 == $n ? '' : "http://example.com/page/%#%/", "%_%");
    

    where we have two cases:

    n=1:     $link = str_replace('%_%', '', "%_%");
    
    n>1:     $link = str_replace('%_%', "http://example.com/page/%#%/", "%_%");
    

    and after the replacement:

    n=1:     $link = '';
    
    n>1:     $link = "http://example.com/page/%#%/";
    

    Here is an example of the output from paginate_links():

    <ul class='page-numbers'>
        <li><a class="prev page-numbers" href="http://example.com/page/2/">&laquo; Previous</a></li>
        <li><a class='page-numbers' href=''>1</a></li>
        <li><a class='page-numbers' href='http://example.com/page/2/'>2</a></li>
        <li><span class='page-numbers current'>3</span></li>
        <li><a class='page-numbers' href='http://example.com/page/4/'>4</a></li>
        <li><a class='page-numbers' href='http://example.com/page/5/'>5</a></li>
        <li><a class='page-numbers' href='http://example.com/page/6/'>6</a></li>
        <li><a class="next page-numbers" href="http://example.com/page/4/">Next &raquo;</a></li>
    </ul>
    

    If you use instead (#):

    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
    'format' => '?paged=%#%',
    

    then you get:

    $link = str_replace('%_%', 1 == $n ? '' : "?paged=%#%", "http://example.com/page/%#%"); 
    

    Since no replacement will take place

    $link = "http://example.com/page/%#%";  
    

    in both cases (n=1 and n>1) and you have a non empty first page link with the output of paginate_links():

    <ul class='page-numbers'>
        <li><a class="prev page-numbers" href="http://example.com/page/2/">&laquo; Previous</a></li>
        <li><a class='page-numbers' href='http://example.com/page/1/'>1</a></li>
        <li><a class='page-numbers' href='http://example.com/page/2/'>2</a></li>
        <li><span class='page-numbers current'>3</span></li>
        <li><a class='page-numbers' href='http://example.com/page/4/'>4</a></li>
        <li><a class='page-numbers' href='http://example.com/page/5/'>5</a></li>
        <li><a class='page-numbers' href='http://example.com/page/6/'>6</a></li>
        <li><a class="next page-numbers" href="http://example.com/page/4/">Next &raquo;</a></li>
    </ul>
    

    To have a non empty first page link it looks like $format can be any string as long as $base doesn’t include the string "%_%", i.e. these should work fine:

    'format' => '?paged=%#%',
    'format' => 'page/%#%',
    'format' => 'asdfasdfasdfasdfasdf',
    

    If you don’t use permalinks, then the example in (#) will also give you non empty first page link since

    $link = str_replace('%_%', 1 == $n ? '' : "?paged=%#%", "http://example.com/?paged=%#%");   
    

    with replacements.

  2. Thanks birgire for help. I’m sharing the result of my paginate_links() which are working with custom taxonomy pages exactly as I need.

    Hope this will help someone to fix it as quick as possible.

    So here it is:

    if (empty($pagerange)) {
        $pagerange = 2;
    }
    global $paged;
    if (empty($paged)) {
        $paged = 1;
    }
    if ($numpages == '') {
        global $wp_query;
        $numpages = $wp_query->max_num_pages;
        if(!$numpages) {
            $numpages = 1;
        }
    }        
        $pagination_args = array(
         'base'            => str_replace('%_%', 1 == $paged ? '' : "?page=%#%", "?page=%#%"),
         'format'          => '?page=%#%',
         'total'           => $numpages,
         'current'         => $paged,
         'show_all'        => False,
         'end_size'        => 1,
         'mid_size'        => $pagerange,
         'prev_next'       => True,
         'prev_text'       => __('<i class="fa fa-angle-left"></i>'),
         'next_text'       => __('<i class="fa fa-angle-right"></i>'),
         'type'            => 'list',
         'add_args'        => false,
         'add_fragment'    => ''
        );
    
    $paginate_links = paginate_links($pagination_args);
    
    if ($paginate_links) {
        echo "<nav class='custom-pagination'><ul>";
        echo $paginate_links;
        echo "</ul></nav>";
    }
    
  3. I stumbled on a same problem and found out that I can replace:

    'current' => max( 1, get_query_var('paged') ),
    

    with:

    'current' => max( 1, get_query_var('page') ),
    

    So just renamed ‘paged’ >’page’ in query var and it works.

  4. Bobz solution worked for me:

    if ( get_query_var('paged') ) { 
        $paged = get_query_var('paged'); 
    } elseif ( get_query_var('page') ) {
        $paged = get_query_var('page'); 
    } else { 
        $paged = 1; 
    }
    
    echo paginate_links(array(
        'current' => $paged,
        'prev_text' => __('Anterior'),
        'next_text' => __('Siguiente'),
        'total' => $variable->max_num_pages
    ));