1

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
    Nobody quite understands how the rewriting of paginate_links() works, but there's an arg add_fragment for adding fragments. Also try not setting base and format & letting paginate_links() work out the link itself (but if that doesn't work then try just get_pagenum_link( $big, false /*escape*/ ) - no wrapping in esc_url() - instead to avoid the #38; (escaped &) issue)... – bonger Jul 23 '15 at 0:01
  • Thanks @bonger! This works perfectly. I don't know how I haven't seen the add_fragment arg... I have updated my code. The last problem is that the anchor is not added for previous link but I can't figure out why. – Pipo Jul 23 '15 at 7:42
  • Just tried the new code and am getting the anchor ("#result") on all links including previous so not sure what's happening there... – bonger Jul 23 '15 at 8:33
  • Ok, so that might come from my query, I will post an update on the question. – Pipo Jul 23 '15 at 8:43
  • @bonger You are right, the code is working fine in Chrome and FF. The problem only appears in Safari. It seems that it Safari handles the redirection differently but I still haven't find how to correct this issue. – Pipo Jul 23 '15 at 14:09
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/%', '/', $link );
}

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

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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