Не за#буйте с вашей пагинацией!!!
Решаем один из самых популярных вопросов у разработчиков WordPress: «Почему не работает пагинация?»
Так почему же?
Для начала нужно разобраться с тем, на какой странице вы хотите вывести пагинацию.
Существуют страницы постов (постов/страниц/кастомных типов постов(CPT)) или архивные страницы(архивные/терминов страницы и страница поиска).
Пагинация на странице постов
В целом пагинацию можно разбить на 3 небольших этапа:
- Делаем правильную выборку с помощью
WP_Query
; - Выводим пагинацию;
- Выводим 404, когда это необходимо
WP_Query для пагинации
$current = absint( max( 1, get_query_var( 'paged' ) ? get_query_var( 'paged' ) : get_query_var( 'page' ) ) ); $posts_per_page = 3; $query = new WP_Query( [ 'post_type' => 'post', 'posts_per_page' => $posts_per_page, 'paged' => $current, ] );
Нужно обратить внимание на параметр paged
в WP_Query
, он говорит о том, какую страницу данного запроса вывести. С помощью функций get_query_var()
мы получаем номер текущей страницы …/page/{# страницы}. В зависимости от типа страницы мы должны использовать get_query_var( 'paged' )
или get_query_var( 'page' )
. Я решил написать универсальный вариант, который подойдет к любому типу страниц.
Вывод пагинации
Для вывода пагинации используем функцию paginate_links
:
echo wp_kses_post( paginate_links( [ 'total' => $query->max_num_pages, 'current' => $current, ] ) );
В функцию paginate_links
нужно передать два параметра: total — количество страниц и current — текущую страницу.
Так же можно использовать the_posts_pagination
, но важно помнить, что данная функция работает только с глобальным wp_query
и ее вызов выглядит примерно так:
global $wp_query; $restore_wp_query = $wp_query; $wp_query = $query; the_posts_pagination(); $wp_query = $restore_wp_query;
Вывод 404 в случае, когда данных нет
if ( $query->have_posts() ) { ... } else { global $wp_query; $wp_query->set_404(); status_header( 404 ); nocache_headers(); require get_404_template(); }
Устанавливаем 404 ответ в глобальный WP_Query
. Ставим 404 статус ответа для сервера. nocache_headers
— позволяет сбросить кеш для заголовков ответа во всех браузерах. И подключаем 404 страницу с помощью require get_404_template()
.
Важно, чтобы до вывода данных ф-ций ничего не выводилось на странице!
Результат
$current = absint( max( 1, get_query_var( 'paged' ) ? get_query_var( 'paged' ) : get_query_var( 'page' ) ) ); $posts_per_page = 3; $query = new WP_Query( [ 'post_type' => 'post', 'posts_per_page' => $posts_per_page, 'paged' => $current, ] ); if ( $query->have_posts() ) { ?> <h1>Текущая страница <?php echo absint( $current ); ?></h1> <?php while ( $query->have_posts() ) { $query->the_post(); the_title(); echo '<br>'; } wp_reset_postdata(); echo wp_kses_post( paginate_links( [ 'total' => $query->max_num_pages, 'current' => $current, ] ) ); } else { global $wp_query; $wp_query->set_404(); status_header( 404 ); nocache_headers(); require get_404_template(); }
Пагинация на архивный страницах
Например я хочу сделать так, чтобы на странице поиска отображались записи только с конкретной категории. Тут важно понимать, что пагинация из примера выше работать не будет т.к. страница поиска является архивной страницей и имеет свою пагинацию. На архивных страницах можно изменить глобальный WP_Query
с помощью хука pre_get_posts
.
Пример страницы
if ( have_posts() ) { while( have_posts() ) { the_post(); the_title(); echo '<br>'; } wp_reset_postdata(); }
Пагинация
Для архивных страниц можно использовать функцию the_posts_pagination
.
if ( have_posts() ) { while( have_posts() ) { the_post(); the_title(); echo '<br>'; } wp_reset_postdata(); the_posts_pagination(); }
Важно, что данная функция работает только с глобальным wp_query
.
Изменяем результат запроса с помощью pre_get_posts
Добавляем в functions.php
:
add_action( 'pre_get_posts', 'customize_search_query' ); function customize_search_query( WP_Query $wp_query ) { if ( $wp_query->is_main_query() && ! $wp_query->is_admin() && $wp_query->is_search() ) { $wp_query->set( 'cat', 10 ); } }
С данным хуком нужно быть осторожным. Для начала нужно проверить, что данный запрос является основным с помощью метода is_main_query
. Так же проверить, что данных запрос вызывается на фронте с помощью is_admin
и то, что данный запрос является поиском is_search
. Затем устанавливаем конкретную категорию set( 'cat', 10 );
Источник: WP Punk.