Альтернатива фукнции пагинации paginate_links()
paginate_links() всегда возвращает HTML, даже если параметр type=array
вы получите массив готовых <a>
тегов. Это может не подойти когда нужно полностью изменить HTML-структуру вашей пагинации. Ниже небольшая функция, которая возвращает массив объектов вместо HTML.
/** * Generates array of pagination links. * * @author Kama (wp-kama.com) * @varsion 2.5 * * @param array $args { * * @type int $total Maximum allowable pagination page. * @type int $current Current page number. * @type string $url_base URL pattern. Use `{pagenum}` placeholder. * @type string $first_url URL to first page. Default: '' - taken automaticcaly from $url_base. * @type int $mid_size Number of links before/after current: 1 ... 1 2 [3] 4 5 ... 99. Default: 2. * @type int $end_size Number of links at the edges: 1 2 ... 3 4 [5] 6 7 ... 98 99. Default: 1. * @type bool $show_all true - Show all links. Default: false. * @type string $a_text_patt `%s` will be replaced with number of pagination page. Default: `'%s'`. * @type bool $is_prev_next Whether to show prev/next links. « Previou 1 2 [3] 4 ... 99 Next ». Default: false. * @type string $prev_text Default: `« Previous`. * @type string $next_text Default: `Next »`. * } * * @return array */ function kama_paginate_links_data( array $args ): array { global $wp_query; $args += [ 'total' => 1, 'current' => 0, 'url_base' => '/{pagenum}', 'first_url' => '', 'mid_size' => 2, 'end_size' => 1, 'show_all' => false, 'a_text_patt' => '%s', 'is_prev_next' => false, 'prev_text' => '« Previous', 'next_text' => 'Next »', ]; $rg = (object) $args; $total_pages = max( 1, (int) ( $rg->total ?: $wp_query->max_num_pages ) ); if( $total_pages === 1 ){ return []; } // fix working parameters $rg->total = $total_pages; $rg->current = max( 1, abs( $rg->current ?: get_query_var( 'paged', 1 ) ) ); $rg->url_base = $rg->url_base ?: str_replace( PHP_INT_MAX, '{pagenum}', get_pagenum_link( PHP_INT_MAX ) ); $rg->url_base = wp_normalize_path( $rg->url_base ); if( ! $rg->first_url ){ // /foo/page(d)/2 >>> /foo/ /foo?page(d)=2 >>> /foo/ $rg->first_url = preg_replace( '~/paged?/{pagenum}/?|[?]paged?={pagenum}|/{pagenum}/?~', '', $rg->url_base ); $rg->first_url = user_trailingslashit( $rg->first_url ); } // core array if( $rg->show_all ){ $active_nums = range( 1, $rg->total ); } else { if( $rg->end_size > 1 ){ $start_nums = range( 1, $rg->end_size ); $end_nums = range( $rg->total - ($rg->end_size - 1), $rg->total ); } else { $start_nums = [ 1 ]; $end_nums = [ $rg->total ]; } $from = $rg->current - $rg->mid_size; $to = $rg->current + $rg->mid_size; if( $from < 1 ){ $to = min( $rg->total, $to + absint( $from ) ); $from = 1; } if( $to > $rg->total ){ $from = max( 1, $from - ($to - $rg->total) ); $to = $rg->total; } $active_nums = array_merge( $start_nums, range( $from, $to ), $end_nums ); $active_nums = array_unique( $active_nums ); $active_nums = array_values( $active_nums ); // reset keys } // fill by core array $pages = []; if( 1 === count( $active_nums ) ){ return $pages; } $item_data = static function( $num ) use ( $rg ){ $data = [ 'is_current' => false, 'page_num' => null, 'url' => null, 'link_text' => null, 'is_prev_next' => false, 'is_dots' => false, ]; if( 'dots' === $num ){ return (object) ( [ 'is_dots' => true, 'link_text' => '…', ] + $data ); } $is_prev = 'prev' === $num && ( $num = max( 1, $rg->current - 1 ) ); $is_next = 'next' === $num && ( $num = min( $rg->total, $rg->current + 1 ) ); $data = [ 'is_current' => ! ( $is_prev || $is_next ) && $num === $rg->current, 'page_num' => $num, 'url' => 1 === $num ? $rg->first_url : str_replace( '{pagenum}', $num, $rg->url_base ), 'is_prev_next' => $is_prev || $is_next, ] + $data; if( $is_prev ){ $data['link_text'] = $rg->prev_text; } elseif( $is_next ) { $data['link_text'] = $rg->next_text; } else { $data['link_text'] = sprintf( $rg->a_text_patt, $num ); } return (object) $data; }; foreach( $active_nums as $indx => $num ){ $pages[] = $item_data( $num ); // set dots $next = $active_nums[ $indx + 1 ] ?? null; if( $next && ($num + 1) !== $next ){ $pages[] = $item_data( 'dots' ); } } if( $rg->is_prev_next ){ $rg->current !== 1 && array_unshift( $pages, $item_data( 'prev' ) ); $rg->current !== $rg->total && $pages[] = $item_data( 'next' ); } return $pages; }
Что выводит функция:
$links_data = kama_paginate_links_data( [ 'total' => 3, 'current' => 2, 'url_base' => 'http://site.com/page-name/paged/{pagenum}', 'mid_size' => 2, ] ); print_r( $links_data ); /* Array ( [0] => stdClass Object ( [is_current] => [page_num] => 288 [url] => http://site.com/page-name/paged/288 [is_prev_next] => 1 [link_text] => « Previous [is_dots] => ) [1] => stdClass Object ( [is_current] => [page_num] => 1 [url] => http://site.com/page-name/ [is_prev_next] => [link_text] => 1 [is_dots] => ) [2] => stdClass Object ( [is_dots] => 1 [link_text] => … [is_current] => [page_num] => [url] => [is_prev_next] => ) [3] => stdClass Object ( [is_current] => [page_num] => 285 [url] => http://site.com/page-name/paged/285 [is_prev_next] => [link_text] => 285 [is_dots] => ) [4] => stdClass Object ( [is_current] => [page_num] => 286 [url] => http://site.com/page-name/paged/286 [is_prev_next] => [link_text] => 286 [is_dots] => ) [5] => stdClass Object ( [is_current] => 1 [page_num] => 287 [url] => http://site.com/page-name/paged/287 [is_prev_next] => [link_text] => 287 [is_dots] => ) ) */
Теперь используем эту функцию в цикле:
<?php $links_data = kama_paginate_links_data( [ 'total' => 3, 'current' => 2, 'url_base' => 'http://site.com/page-name/paged/{pagenum}', ] ); if( $links_data ){ ?> <ul> <?php foreach( $links_data as $link ) { ?> <li> <?php if ( $link->is_dots ) { ?> <span><?= $link->link_text ?></span> <?php } elseif ( $link->is_current ) { ?> <strong><?= $link->link_text ?></strong> <?php } else { ?> <a href="<?php esc_attr_e( $link->url ) ?>"><?php _e( $link->link_text ) ?></a> <?php } ?> </li> <?php } ?> </ul> <?php }
Получим:
<ul> <li> <a href="http://site.com/page-name/paged/1">1</a> </li> <li> <strong>2</strong> </li> <li> <a href="http://site.com/page-name/paged/3">3</a> </li> </ul>
—
Эта заметка встроена в: paginate_links()