Adding anchor to paginate_links + Safari anchor bug

I don’t quite understand how the rewriting of pagination_links() works. Here is my pagination function :

$big = 999999999;
$translated = __( 'Page ', 'epc' );

echo paginate_links( array(
    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
    'format' => '?page=%#%', // Here I'd like to add my anchor #result
    'current' => max( 1, get_query_var( 'paged' ) ),
    'total' => $wp_query->max_num_pages,
    'before_page_number' => '<span class="screen-reader-text">'.$translated.' </span>',
    'prev_text' => __( 'Précédent', 'epc' ),
    'next_text' => __( 'Suivant', 'epc' ),
    'type' => 'list',
    ) 
);

However, I have pretty permalink turned on so the format ?page=%#% is changed to /page/#/. So far so good. But I have two problems :

  • First, my query has two variables in the permalink like so ?programme=10&type=2. When I go on the second page, wordpress adds #038;type=2 at the end of the permalink (now I have ?programme=10&type=2#038;type=2). I don’t know why.

  • Second, if I try to add an anchor to the format like so ?page=%#%#result it will not work. If I try to rename the variable to ?nb=%#%#result it’s still not working. I even tried /page/#/#result as it fits the pretty permalink structure but still no luck. Can someone put me on the right track or explain what is happening here?

Thanks!


UPDATE 1

Thanks to @bonger comment, the permalink works perfectly with this updated code:

$big = 999999999;
$translated = __( 'Page ', 'epc' );
echo paginate_links( array(
    'base' => str_replace( $big, '%#%', get_pagenum_link( $big, false ) ),
    'current' => max( 1, get_query_var( 'paged' ) ),
    'total' => $wp_query->max_num_pages,
    'before_page_number' => '<span class="screen-reader-text">'.$translated.' </span>',
    'prev_text' => __( 'Précédent', 'epc' ),
    'next_text' => __( 'Suivant', 'epc' ),
    'type' => 'list',
    'add_fragment' => '#result',
) );

However, after digging a little bit more, when clicked, the previous link looses the anchor in Safari only (works fine in Chrome and Firefox). I’ve read this old post and it seems that there is something weird with how Safari handles the redirect.

Right know, my previous link displays this href http://mywebsite.com/page/1/#result or http://mywebsite.com/page/1/?programme=10&type=2#result depending on the filtering. However, when I click on it, it redirects to http://mywebsite.com/ or http://mywebsite.com/?programme=10&type=2. Apparently, Safari needs the / before the #anchorbut I am not sure how to add this as if I add it to the fragment arg, it gets escaped. Any ideas?

1 Answer
1

If it can help anyone, here is the full answer with the issues that might happen when you want to add WordPress pagination with anchors to a template page.


STEP 1

Follow the example on the Codex so that the paginate_links() function applies to your custom query and not to the main query.


STEP 2

Your function should look like the code below :

global $wp_query;

$big = 999999999; // need an unlikely integer
$translated = __( 'Page', 'mytextdomain' ); // Supply translatable string

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,
    'before_page_number' => '<span class="screen-reader-text">'.$translated.' </span>'
) );

Now, several issues can happen with this code, here are a couple of solutions:

  • It’s better if you remove the 'format' => '?paged=%#%', line and let WordPress do is job with formatting permalink (it can cause issues with pretty permalink turned on) ;

  • You can have an escaping problem with the # of your anchor if you escape the get_pagenum_link()function output. In this case, just remove the esc_url() function in this part esc_url( get_pagenum_link( $big ) ) ;

  • There is an argument to add your anchor, it is called add_fragment.

Check the codex to see all the arguments you can use with this function. In the end, your code will look something like this:

$big = 999999999;
$translated = __( 'Page', 'mytextdomain' );
echo paginate_links( array(
    'base' => str_replace( $big, '%#%', get_pagenum_link( $big, false ) ),
    'current' => max( 1, get_query_var( 'paged' ) ),
    'total' => $wp_query->max_num_pages,
    'before_page_number' => '<span class="screen-reader-text">'.$translated.' </span>',
    'prev_text' => __( 'Précédent', 'epc' ), // In case you want to change the previous link text
    'next_text' => __( 'Suivant', 'epc' ), In case you want to change the next link text
    'type' => 'list', // How you want the return value to be formatted
    'add_fragment' => '#result', // Your anchor
) );

STEP 3

To finish, there is a problem with how Safari handles the redirection of pages with anchor. You might find out that the anchor is not applied when going back to first page on Safari. What you need to do (if you have pretty permalink turned on) is to filter ou the page/1 to prevent redirection. Like so:

add_filter( 'paginate_links', 'custom_pagination_redirect' );

function custom_pagination_redirect( $link ) {
    return preg_replace( '%/page/1/%', "https://wordpress.stackexchange.com/", $link );
}

And that’s it! Thanks a lot to @bonger for the precious help!

Leave a Comment