paginate_links( string|array $args = '' )

Retrieve paginated link for archive post pages.


Description 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.


Parameters Parameters

$args

(string|array) (Optional) Array or string of arguments for generating paginated links for archives.

  • 'base'
    (string) Base of the paginated url.
  • 'format'
    (string) Format for the pagination structure.
  • 'total'
    (int) The total amount of pages. Default is the value WP_Query's max_num_pages or 1.
  • 'current'
    (int) The current page number. Default is 'paged' query var or 1.
  • 'aria_current'
    (string) The value for the aria-current attribute. Possible values are 'page', 'step', 'location', 'date', 'time', 'true', 'false'. Default is 'page'.
  • 'show_all'
    (bool) Whether to show all pages. Default false.
  • 'end_size'
    (int) How many numbers on either the start and the end list edges. Default 1.
  • 'mid_size'
    (int) How many numbers to either side of the current pages. Default 2.
  • 'prev_next'
    (bool) Whether to include the previous and next links in the list. Default true.
  • 'prev_text'
    (bool) The previous page text. Default '« Previous'.
  • 'next_text'
    (bool) The next page text. Default 'Next »'.
  • 'type'
    (string) Controls format of the returned value. Possible values are 'plain', 'array' and 'list'. Default is 'plain'.
  • 'add_args'
    (array) An array of query args to add. Default false.
  • 'add_fragment'
    (string) A string to append to each link.
  • 'before_page_number'
    (string) A string to appear before the page number.
  • 'after_page_number'
    (string) A string to append after the page number.

Default value: ''


Top ↑

Return Return

(string|array|void) String of page links or array of page links.


Top ↑

Source Source

File: wp-includes/general-template.php

3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
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' ) ? intval( 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;
 
    if ( $args['prev_next'] && $current && 1 < $current ) :
        $link = str_replace( '%_%', 2 == $current ? '' : $args['format'], $args['base'] );
        $link = str_replace( '%#%', $current - 1, $link );
        if ( $add_args ) {
            $link = add_query_arg( $add_args, $link );
        }
        $link .= $args['add_fragment'];
 
        /**
         * Filters the paginated links for the given archive pages.
         *
         * @since 3.0.0
         *
         * @param string $link The paginated link URL.
         */
        $page_links[] = '<a class="prev page-numbers" href="' . esc_url( apply_filters( 'paginate_links', $link ) ) . '">' . $args['prev_text'] . '</a>';
    endif;
    for ( $n = 1; $n <= $total; $n++ ) :
        if ( $n == $current ) :
            $page_links[] = "<span aria-current='" . esc_attr( $args['aria_current'] ) . "' class='page-numbers current'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . '</span>';
            $dots         = true;
        else :
            if ( $args['show_all'] || ( $n <= $end_size || ( $current && $n >= $current - $mid_size && $n <= $current + $mid_size ) || $n > $total - $end_size ) ) :
                $link = str_replace( '%_%', 1 == $n ? '' : $args['format'], $args['base'] );
                $link = str_replace( '%#%', $n, $link );
                if ( $add_args ) {
                    $link = add_query_arg( $add_args, $link );
                }
                $link .= $args['add_fragment'];
 
                /** This filter is documented in wp-includes/general-template.php */
                $page_links[] = "<a class='page-numbers' href='" . esc_url( apply_filters( 'paginate_links', $link ) ) . "'>" . $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] . '</a>';
                $dots         = true;
            elseif ( $dots && ! $args['show_all'] ) :
                $page_links[] = '<span class="page-numbers dots">' . __( '&hellip;' ) . '</span>';
                $dots         = false;
            endif;
        endif;
    endfor;
    if ( $args['prev_next'] && $current && $current < $total ) :
        $link = str_replace( '%_%', $args['format'], $args['base'] );
        $link = str_replace( '%#%', $current + 1, $link );
        if ( $add_args ) {
            $link = add_query_arg( $add_args, $link );
        }
        $link .= $args['add_fragment'];
 
        /** This filter is documented in wp-includes/general-template.php */
        $page_links[] = '<a class="next page-numbers" href="' . esc_url( apply_filters( 'paginate_links', $link ) ) . '">' . $args['next_text'] . '</a>';
    endif;
    switch ( $args['type'] ) {
        case 'array':
            return $page_links;
 
        case 'list':
            $r .= "<ul class='page-numbers'>\n\t<li>";
            $r .= join( "</li>\n\t<li>", $page_links );
            $r .= "</li>\n</ul>\n";
            break;
 
        default:
            $r = join( "\n", $page_links );
            break;
    }
    return $r;
}

Top ↑

Changelog Changelog

Changelog
Version Description
4.9.0 Added the aria_current argument.
2.1.0 Introduced.


Top ↑

User Contributed Notes User Contributed Notes

  1. Skip to note 1 content
    Contributed by Codex

    Example With a Custom Query
    When querying a loop with new WP_Query set the total parameter to the max_num_pages property of the WP_Query object.

    Example of a custom query:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    //Protect against arbitrary paged values
    $paged = ( get_query_var( 'paged' ) ) ? absint( get_query_var( 'paged' ) ) : 1;
     
    $args = array(
        'posts_per_page' => 5,
        'category_name' => 'gallery',
        'paged' => $paged,
    );
     
    $the_query = new WP_Query( $args );
    ?>
    <!-- the loop etc.. -->

    Example of paginate_links parameters adapted to the custom query above:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
    $big = 999999999; // need an unlikely integer
     
    echo paginate_links( array(
        'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
        'format' => '?paged=%#%',
        'current' => max( 1, get_query_var('paged') ),
        'total' => $the_query->max_num_pages
    ) );
    ?>
  2. Skip to note 2 content
    Contributed by Codex

    Improving Accessibility
    To add context to the numbered links to ensure that screen reader users understand what the links are for:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?php
    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>'
    ) );
    ?>
  3. Skip to note 3 content
    Contributed by Codex

    Basic Example
    To add pagination to your search results and archives, you can use the following example:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php
    global $wp_query;
     
    $big = 999999999; // need an unlikely integer
     
    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
    ) );
    ?>
  4. Skip to note 4 content
    Contributed by Chetan Prajapati
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php
    global $wp_query;
     
    $big = 999999999; // need an unlikely integer
     
    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
    ) );
    ?>

    Aligned array items properly based on WPCS.

  5. Skip to note 5 content
    Contributed by Binsaifullah
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // first create a function
    function pagainate_link_function(){
        global $wp_query;
        echo paginate_links(array(
            'current'=>max(1,get_query_var('paged')),
            'total'=>$wp_query->max_num_pages,
            'type'=>'list', //default it will return anchor
        ));
    }
     
    // Now call this function in your desired place

You must log in before being able to contribute a note or feedback.