Ошибка 404 при пагинации пользовательского запроса в WordPress
Основная проблема в том, что все страницы пагинации в моем блоге (/page/2/, /page/3/ и т.д.) ведут на страницу 404. Раньше все работало нормально, но сейчас перестало. Возможно, это связано с обновлением до версии 3.9.
Вот что я уже пробовал сделать для исправления этой проблемы (ни один из вариантов не сработал - страницы пагинации по-прежнему возвращают 404):
- Отключал все плагины
- Несколько раз сбрасывал настройки постоянных ссылок
- Пробовал использовать стандартные permalinks вместо /postname
- Проверил, что в Настройках чтения → "На странице блога отображать не более" установлено то же значение, что и в моем цикле (а также тестировал с разными значениями)
- Пробовал два разных плагина для навигации и стандартную wordpress пагинацию ("Старые записи") - все равно 404
- Пробовал использовать parse_query
- Пробовал paginate_links
Вот мой код:
home.php
<?php require dirname( __FILE__ ) . '/blog-page.php';
blog-page.php
<?php
/*
Шаблон: Blog Page - Custom
*/
get_header(); ?>
<---ПОЛЬЗОВАТЕЛЬСКИЙ КОД--->
<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'posts_per_page' => 5,
'post_type' => 'post',
'paged' => $paged
);
$wp_query = new WP_Query($args);
if($wp_query->have_posts()) :
while($wp_query->have_posts()) : $wp_query->the_post(); ?>
<---ПОЛЬЗОВАТЕЛЬСКИЙ КОД--->
endwhile;
wp_reset_postdata();?>
<div class="nav-previous alignleft"><?php next_posts_link( 'Старые записи' ); ?></div>
<div class="nav-next alignright"><?php previous_posts_link( 'Новые записи' ); ?></div>
<?php endif; wp_reset_query();
Для теста я создал тестовый сайт с этой проблемой. На нем оставлена стандартная wordpress пагинация.
У меня закончились идеи. Буду благодарен за любые предложения по решению этой проблемы.

Есть несколько моментов, которые мне непонятны, но я постараюсь ответить на них по ходу дела.
У вас есть home.php, который, как я понимаю, является вашей главной страницей по умолчанию. В нем всего одна строка кода, которая вызывает другой шаблон страницы. Вот ваш код:
<?php require dirname( __FILE__ ) . '/blog-page.php';
В blog-page.php у вас полный шаблон страницы. Мой вопрос: зачем вы так делаете? Почему бы просто не добавить содержимое blog-page.php в home.php? Так было бы логичнее.
Вы не используете основной запрос для вашего цикла, а создаете кастомный, что мне тоже непонятно, так как ваш кастомный запрос делает то же самое, что и основной, за исключением количества постов на странице. Весь этот кастомный запрос можно избежать, просто используя pre_get_posts
для установки нужного количества постов на главной странице.
function posts_on_homepage( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '5' );
}
}
add_action( 'pre_get_posts', 'posts_on_homepage' );
Вы можете просто добавить это в functions.php, что установит количество постов на главной странице равным 5, и тогда вы сможете заменить кастомный запрос обычным циклом.
Одна важная вещь: когда вы используете кастомный запрос, пагинация не будет работать, как указано в комментариях.
Вам нужно изучить параметры пагинации WP_Query
.
paged (int) - номер страницы. Показывает посты, которые обычно отображаются на странице X при использовании ссылки "Старые записи".
page (int) - номер страницы для статической главной страницы. Показывает посты, которые обычно отображаются на странице X статической главной страницы.
Таким образом, ваш запрос для обычных страниц должен выглядеть так:
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$query = new WP_Query( array( 'paged' => $paged ) );
А для статических страниц - так:
$paged = ( get_query_var('page') ) ? get_query_var('page') : 1;
$query = new WP_Query( array( 'paged' => $paged ) );
Вы также дважды сбрасываете данные поста. Это нужно делать только один раз. Кстати, wp_reset_query();
использовать неверно - он предназначен только для query_posts
, который вообще не рекомендуется использовать. Вместо этого используйте wp_reset_postdata();
.
Наконец, при использовании кастомного запроса вы должны указать максимальное количество страниц для next_posts_link
, используя параметр $max_pages
, иначе он не будет работать.
next_posts_link( 'Старые записи', $the_query->max_num_pages );
Вот пример правильно работающего кастомного запроса из кодекса:
<?php
// устанавливаем параметр "paged" (используйте 'page' для статической главной страницы)
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
// запрос
$the_query = new WP_Query( 'cat=1&paged=' . $paged );
?>
<?php if ( $the_query->have_posts() ) : ?>
<?php
// цикл
while ( $the_query->have_posts() ) : $the_query->the_post();
?>
<?php the_title(); ?>
<?php endwhile; ?>
<?php
// использование next_posts_link() с max_num_pages
next_posts_link( 'Старые записи', $the_query->max_num_pages );
previous_posts_link( 'Новые записи' );
?>
<?php
// очищаем данные после запроса
wp_reset_postdata();
?>
<?php else: ?>
<p><?php _e( 'Извините, нет записей, соответствующих вашим критериям.' ); ?></p>
<?php endif; ?>
Надеюсь, это прольет свет на вашу проблему.

Огромное спасибо за то, что нашли время написать такой подробный ответ. Я перепробовал так много вариантов, что, кажется, окончательно запутался. Обязательно сохраню ваши рекомендации — они мне еще не раз пригодятся. Я скопировал свой код из blog-page.php и перенес его в home.php. Перешел на стандартный запрос. Затем добавил вашу функцию для ограничения количества записей. Хотя лимит был установлен в настройках чтения, страница его игнорировала даже после переноса в home.php. Есть идеи, почему так происходило? В любом случае, теперь все работает идеально. Не могу выразить, как я благодарен за вашу помощь.

Вы установили главную страницу в "Настройки чтения >> Отображение главной страницы"? Если нет, отредактируйте свой вопрос и добавьте текущий код из home.php, чтобы я мог быстро взглянуть :)

Да, я это настроил. Смотрите здесь: http://imgur.com/n8YINbI Вот мой новый home.php http://pastebin.com/bTHRMFqT Если я удаляю вашу функцию, отображаются все записи и нет пагинации. Если добавляю функцию — отображается правильное количество записей, и все работает как должно.

Я опоздал на вечеринку, но ни один из вышеперечисленных вариантов мне не помог. Мне удалось написать небольшой обходной путь для этой совершенно раздражающей ситуации.
- Изучите URL
- Если присутствует /page/2, напишите правило перенаправления, чтобы добавить строку запроса к URL
- Используйте этот запрос в своей пагинации.
// Установка глобальной переменной для сегментов URL (functions.php)
global $segments;
$segments = explode('/', $_SERVER['REQUEST_URI']);
$segments = array_filter($segments);
$segments['classes'] = implode(' ', $segments);
// Добавьте это правило перезаписи в functions.php для добавления строки запроса к цели
add_action( 'init', 'forum_paging_redirect', 10 );
function forum_paging_redirect( $redirect_url ) {
global $segments;
if($segments[1] === 'forum' && $segments[2] === 'page') {
echo '<script>window.location = "/forum?topics_page='.$segments[3].'";</script>';
}
}
// Вместо нативной функции пагинации выведите это:
if(!empty($query_topics)) {
$total = $query_topics->max_num_pages;
$page = $_GET['topics_page'];
for($i = 1; $i < $total +1; $i++) {
if($i == $page) {
echo '<span aria-current="page" class="page-numbers current">'.$i.'</span>';
} else {
echo '<a class="page-numbers" href="/forum/?topics_page='.$i.'">'.$i.'</a>';
}
}
}
