My generated paginate link results will have additional #038;
in the url, may I know how to get rid of it?
Blog page url :
http://localhost/wordpress/blog/
I had already setup pagination with function paginate_links, when I press page [2] :
Blog page Page 2 url :
http://localhost/wordpress/blog/page/2/
( everything is fine above )
However, whenever my Blog page URL have certain parameters which is for my filter/sorting purposes for WP_Query, the paginate_link result will have additional #038 params , please refer below for the URL
Blog page with Params Url :
http://localhost/wordpress/blog/?filter=23&orderby=oldest
Blog page with Params Page 2 Url :
http://localhost/wordpress/blog/page/2/?filter=23&orderby=oldest#038;orderby=oldest
The URL I need to achieve is
http://localhost/wordpress/blog/page/2/?filter=23&orderby=oldest
below are my paginate_links functions:
global $wp_query;
$big = 99999999999;
paginate_links([
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'prev_text' => __('<'),
'next_text' => __('>'),
'current' => max( 1, get_query_var('paged') ),
'type' => 'list',
'total' => $wp_query->max_num_pages,
]);
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:
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:
-
Use html_entity_decode()
just as WordPress does via paginate_links()
:
'base' => str_replace( $big, '%#%', html_entity_decode( get_pagenum_link( $big ) ) )
-
When you call get_pagenum_link()
, set the second parameter set to false
:
'base' => str_replace( $big, '%#%', get_pagenum_link( $big, false ) )
-
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..