Почему не работает пагинация?
Один из самых популярных вопрос у разработчиков 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() ) {
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 );
Огромное спасибо, блин, достаточно простой механизм однако, но из-за избытка корявых примеров на просторах сети нихера не работает. Название вашей статьи очень хорошо ложиться на моё состояние в котором я её нашел) Ещё раз спасибо, материал сохраню.