Paginate Link generate additional #038; whenever my Url have multiple Query String

There’s no need to escape the URL twice – get_pagenum_link() by default returns an escaped URL — when the second parameter is true, esc_url() is used; else, esc_url_raw() is used:

  • With esc_url(): http://localhost/wordpress/blog/?filter=23&orderby=oldest

  • With esc_url_raw(): http://localhost/wordpress/blog/?filter=23&orderby=oldest

And the problem occurs when the base contains ?, or a query string, and that the URL is escaped (e.g. using esc_url()).

Because esc_url() converts & (ampersand) to its HTML entity, which is &, and when the base contains a query string, paginate_links() will parse the base value/URL, and when the & is escaped, anything after each & and the nearest = is treated as a query string name/key, and added to the base‘s query string:

http://localhost/wordpress/blog/?filter=23&orderby=oldest#038;orderby=oldest

In the above example, the URL is like that because paginate_links() (or more precisely, wp_parse_str() used in paginate_links()) interpreted #038;orderby as the key of oldest; i.e. #038;orderby=oldest — it should be &orderby=oldest where the key is orderby.

(But of course, the browser sees anything after the # as a URL fragment. And if you follow the link, on the next page, $_GET will not have an entry for #038;orderby; i.e. $_GET['#038;orderby'] doesn’t exist.)

So here are several ways to fix/avoid the problem:

  1. Use html_entity_decode() just as WordPress does via paginate_links():

    'base' => str_replace( $big, '%#%', html_entity_decode( get_pagenum_link( $big ) ) )
    
  2. When you call get_pagenum_link(), set the second parameter set to false:

    'base' => str_replace( $big, '%#%', get_pagenum_link( $big, false ) )
    
  3. Use str_replace() to replace the & with &:

    'base' => str_replace( [ $big, '&' ], [ '%#%', '&' ], get_pagenum_link( $big ) )
    

Don’t worry about not escaping the base because paginate_links() actually escapes all the links/URLs in the returned result.

Friendly Warning: Some of the links in this answer point you to a huge HTML file / web page..

Leave a Comment