paginate_links( string|array $args = '' ): string|string[]|void
- Since
- 2.1.0, 4.9.0
- Source
wp-includes/general-template.php:4500
Description
Technically, the function can be used to create paginated link list for any area. The 'base' argument is used to reference the url, which will be used to create the paginated links. The 'format' argument is then used for replacing the page number. It is however, most likely and by default, to be used on the archive post pages.
The 'type' argument controls format of the returned value. The default is 'plain', which is just a string with the links separated by a newline character. The other possible values are either 'array' or 'list'. The 'array' value will return an array of the paginated link list to offer full control of display. The 'list' value will place all of the paginated links in an unordered HTML list.
The 'total' argument is the total amount of pages and is an integer. The 'current' argument is the current page number and is also an integer.
An example of the 'base' argument is "http://example.com/all_posts.php%_%" and the '%%' is required. The '%%' will be replaced by the contents of in the 'format' argument. An example for the 'format' argument is "?page=%#%" and the '%#%' is also required. The '%#%' will be replaced with the page number.
You can include the previous and next links in the list by setting the 'prev_next' argument to true, which it is by default. You can set the previous text, by using the 'prev_text' argument. You can set the next text by setting the 'next_text' argument.
If the 'show_all' argument is set to true, then it will show all of the pages instead of a short list of the pages near the current page. By default, the 'show_all' is set to false and controlled by the 'end_size' and 'mid_size' arguments. The 'end_size' argument is how many numbers on either the start and the end list edges, by default is 1. The 'mid_size' argument is how many numbers to either side of current page, but not including current page.
It is possible to add query vars to the link by using the 'add_args' argument and see add_query_arg() for more information.
The 'before_page_number' and 'after_page_number' arguments allow users to augment the links themselves. Typically this might be to add context to the numbered links so that screen reader users understand what the links are for.
The text strings are added before and after the page number - within the anchor tag.
Compatibility
- WordPress
- since 4.9.0
- PHP
- 7.4–8.6-dev
- 6.7.7
- 6.8.8
- 6.9.7
- 7.0.4
- 7.1.0
Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.
Parameters
$argsstring|arrayoptional- Array or string of arguments for generating paginated links for archives.Default:
''$basestringdefault: emptyBase of the paginated url.$formatstringdefault: emptyFormat for the pagination structure.$totalintdefault: is the value WP_Query's max_num_pages or 1The total amount of pages.$currentintdefault: is 'paged' query var or 1The current page number.$aria_currentstringdefault: is 'page'The value for the aria-current attribute. Possible values are 'page', 'step', 'location', 'date', 'time', 'true', 'false'.$show_allbooldefault: falseWhether to show all pages.$end_sizeintdefault: 1How many numbers on either the start and the end list edges.$mid_sizeintdefault: 2How many numbers to either side of the current pages.$prev_nextbooldefault: trueWhether to include the previous and next links in the list.$prev_textstringdefault: '« Previous'The previous page text.$next_textstringdefault: 'Next »'The next page text.$typestringdefault: is 'plain'Controls format of the returned value. Possible values are 'plain', 'array' and 'list'.$add_argsarraydefault: falseAn array of query args to add.$add_fragmentstringdefault: emptyA string to append to each link.$before_page_numberstringdefault: emptyA string to appear before the page number.$after_page_numberstringdefault: emptyA string to append after the page number.
Return value
string|string[]|void- String of page links or array of page links, depending on 'type' argument.
Void if total number of pages is less than 2.
Performance profile
How much work a call to paginate_links() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.
- Cost class
- Light
- Scaling
- Scales with input
- Instructions
- 80–229
- Plugin surface
- 2 hooks
- Called by
- 8
Touches nothing outside its own arguments.
The body loops, so the work grows with what you pass in.
Executed per call on PHP 8.5, depending on the branch taken. The body compiles to 353.
Third-party callbacks on 'paginate_links', 'paginate_links_output' run inside this call, and their cost is not bounded by anything here.
8 places in core call this, so the cost is paid more often than your own code shows.
What it touches
- hookthird-party callbacks
apply_filters()called directly
Further down the call graph this can also reach option, cache, serialize, query and transient. Those are the worst case, several calls deep and usually down an error path, not what a normal call pays.
What one call costs · 28 distinct outcomes
One number would be a lie: the work depends on which branch runs. These are every distinct cost paginate_links() can have, taken from its control-flow graph on PHP 8.5.
| When | Instructions | Calls it makes |
|---|---|---|
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) | 80–114 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && !$n | 111–127 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) | 115–150 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && !$n && $current | 134–143 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && !$n && $args && $current | 139–148 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), add_query_arg(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && !$n && $current | 141–156 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && !$n && $args && $current | 146–161 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), add_query_arg(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && !$n | 146–163 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && $current && !$n | 165–170 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), apply_filters(), esc_url(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && !$n && $current | 169–179 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && $current && !$n | 170–175 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), apply_filters(), esc_url(), add_query_arg(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && $current && !$n | 170–175 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), add_query_arg(), apply_filters(), esc_url(), apply_filters(), esc_url() |
16 further outcomes, up to 229 instructions
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && $current && !$n | 172–183 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), apply_filters(), esc_url(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && !$n && $args && $current | 174–184 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), add_query_arg(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && $args && $current && !$n | 175–180 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), add_query_arg(), apply_filters(), esc_url(), add_query_arg(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && !$n && $current | 176–192 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && $current && !$n | 177–188 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), apply_filters(), esc_url(), add_query_arg(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && $current && !$n | 177–188 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), add_query_arg(), apply_filters(), esc_url(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && !$n && $args && $current | 181–197 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), add_query_arg(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && !isset($url_parts) && !$total && $args && $current && !$n | 182–193 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), add_query_arg(), apply_filters(), esc_url(), add_query_arg(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && $current && !$n | 200–206 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), apply_filters(), esc_url(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && $current && !$n | 205–211 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), apply_filters(), esc_url(), add_query_arg(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && $current && !$n | 205–211 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), add_query_arg(), apply_filters(), esc_url(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && $current && !$n | 207–219 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), apply_filters(), esc_url(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && $args && $current && !$n | 210–216 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), add_query_arg(), apply_filters(), esc_url(), add_query_arg(), apply_filters(), esc_url() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && $current && !$n | 212–224 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), apply_filters(), esc_url(), add_query_arg(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && $current && !$n | 212–224 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), add_query_arg(), apply_filters(), esc_url(), apply_filters(), esc_url(), apply_filters() |
!isset($wp_query) && !get_query_var() && !->using_index_permalinks() && !->using_permalinks() && isset($url_parts) && !$total && $args && $current && !$n | 217–229 | get_pagenum_link(), html_entity_decode(), explode(), get_query_var(), trailingslashit(), ->using_index_permalinks(), ->using_permalinks(), __(), __(), wp_parse_args(), explode(), wp_parse_str(), wp_parse_str(), urlencode_deep(), array_merge(), add_query_arg(), apply_filters(), esc_url(), add_query_arg(), apply_filters(), esc_url(), apply_filters() |
This body has more branch combinations than are worth enumerating, so the table covers the outcomes found first rather than every one that exists.
Across PHP versions
| PHP | Compiled | Executed | Branches | Notes |
|---|---|---|---|---|
| 8.6-dev | 352 | 80–229 | 37 | 1 fewer instruction than PHP 8.5 |
| 8.5 | 353 | 80–229 | 37 | |
| 8.4 | 353 | 80–229 | 37 | 32 fewer instructions than PHP 8.3 |
| 8.3 | 385 | 80–248 | 37 | |
| 8.2 | 385 | 80–248 | 37 | 1 more instruction than PHP 8.1 |
| 8.1 | 384 | 80–248 | 37 | 5 fewer instructions than PHP 7.4 |
| 7.4 | 389 | 80–248 | 37 |
An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.
Hooks and filters fired · 4
4 hooks fire while paginate_links() runs, in this order:
- apply_filters( paginate_links )filterline 4598 (+98 into the body)
Filters the paginated links for the given archive pages.
- apply_filters( paginate_links )filterline 4624 (+124 into the body)
Filters the paginated links for the given archive pages.
- apply_filters( paginate_links )filterline 4648 (+148 into the body)
Filters the paginated links for the given archive pages.
- apply_filters( paginate_links_output )filterline 4677 (+177 into the body)
Filters the HTML output of paginated links for archives.
Uses · 13
- get_pagenum_link()Retrieves the link for a page number.
- get_query_var()Retrieves the value of a query variable in the WP_Query class.
- trailingslashit()Appends a trailing slash.
- user_trailingslashit()Retrieves a trailing-slashed string if the site is set for adding trailing slashes.
- __()Retrieves the translation of $text.
- wp_parse_args()Merges user defined arguments into defaults array.
- wp_parse_str()Parses a string into variables to be stored in an array.
- urlencode_deep()Navigates through an array, object, or scalar, and encodes the values to be used in a URL.
- add_query_arg()Retrieves a modified URL query string.
- esc_url()Checks and cleans a URL.
- apply_filters()Calls the callback functions that have been added to a filter hook.
- esc_attr()Escaping for HTML attributes.
Show all 13
- number_format_i18n()Converts float number to format based on the locale.
Used by · 8
- WP_User_Search::do_paging()Handles paging for the user search query.
- get_the_posts_pagination()Retrieves a paginated navigation to next/previous set of posts, when applicable.
- media_upload_library_form()Outputs the legacy media upload form for the media library.
- paginate_comments_links()Displays or retrieves pagination links for the comments on the current post.
- render_block_core_query_pagination_numbers()Renders the `core/query-pagination-numbers` block on the server.
- twentyfourteen_paging_nav()Display navigation to next/previous set of posts when applicable.
- wp_nav_menu_item_post_type_meta_box()Displays a meta box for a post type menu item.
- wp_nav_menu_item_taxonomy_meta_box()Displays a meta box for a taxonomy menu item.
Source code
function paginate_links( $args = '' ) { global $wp_query, $wp_rewrite; // Setting up default values based on the current URL. $pagenum_link = html_entity_decode( get_pagenum_link() ); $url_parts = explode( '?', $pagenum_link ); // Get max pages and current page out of the current query, if available. $total = isset( $wp_query->max_num_pages ) ? $wp_query->max_num_pages : 1; $current = get_query_var( 'paged' ) ? (int) get_query_var( 'paged' ) : 1; // Append the format placeholder to the base URL. $pagenum_link = trailingslashit( $url_parts[0] ) . '%_%'; // URL base depends on permalink settings. $format = $wp_rewrite->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : ''; $format .= $wp_rewrite->using_permalinks() ? user_trailingslashit( $wp_rewrite->pagination_base . '/%#%', 'paged' ) : '?paged=%#%'; $defaults = array( 'base' => $pagenum_link, // http://example.com/all_posts.php%_% : %_% is replaced by format (below). 'format' => $format, // ?page=%#% : %#% is replaced by the page number. 'total' => $total, 'current' => $current, 'aria_current' => 'page', 'show_all' => false, 'prev_next' => true, 'prev_text' => __( '« Previous' ), 'next_text' => __( 'Next »' ), 'end_size' => 1, 'mid_size' => 2, 'type' => 'plain', 'add_args' => array(), // Array of query args to add. 'add_fragment' => '', 'before_page_number' => '', 'after_page_number' => '', ); $args = wp_parse_args( $args, $defaults ); if ( ! is_array( $args['add_args'] ) ) { $args['add_args'] = array(); } // Merge additional query vars found in the original URL into 'add_args' array. if ( isset( $url_parts[1] ) ) { // Find the format argument. $format = explode( '?', str_replace( '%_%', $args['format'], $args['base'] ) ); $format_query = isset( $format[1] ) ? $format[1] : ''; wp_parse_str( $format_query, $format_args ); // Find the query args of the requested URL. wp_parse_str( $url_parts[1], $url_query_args ); // Remove the format argument from the array of query arguments, to avoid overwriting custom format. foreach ( $format_args as $format_arg => $format_arg_value ) { unset( $url_query_args[ $format_arg ] ); } $args['add_args'] = array_merge( $args['add_args'], urlencode_deep( $url_query_args ) ); } // Who knows what else people pass in $args. $total = (int) $args['total']; if ( $total < 2 ) { return; } $current = (int) $args['current']; $end_size = (int) $args['end_size']; // Out of bounds? Make it the default. if ( $end_size < 1 ) { $end_size = 1; } $mid_size = (int) $args['mid_size']; if ( $mid_size < 0 ) { $mid_size = 2; } $add_args = $args['add_args']; $r = ''; $page_links = array(); $dots = false;Changelog
Introduced in 2.1.0. One change between 6.7.7 and 7.1.0.
Signature, return type and hooks compared across 5 parsed releases.
string|string[]|void to string|string[]|null.verified against sourcearia_current argument.from the docblockAbout this page
- Parsed data
- Generated from the wordpress-develop 6.7.7 tag, from
src/wp-includes/general-template.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it. - Corrections
- Something wrong on this page? Report it and it gets fixed in the next regeneration.