Это довольно интересный вопрос (за который я проголосовал, особенно за ваш подход и исследования ). Большой кривая здесь - первая страница запроса:
Вы не можете настроить запрос на возврат 0сообщений на первой странице
Перемещая содержимое каждой страницы вверх на одну страницу, вы потеряете последнюю страницу, поскольку в запросе останется только то же количество сообщений, поэтому $max_num_pagesсвойство останется прежним.
Нам нужно будет как-то «обмануть» WP_Queryкласс, чтобы мы возвращали наши сообщения со смещением в одну страницу, а также получали правильное количество страниц, чтобы не потерять последнюю страницу в запросе.
Давайте посмотрим на следующую идею и попробуем поместить все в код. Прежде чем мы сделаем, я хотел бы сделать несколько замечаний здесь
ВАЖНЫЕ ЗАМЕТКИ:
Все не проверено, поэтому может быть глючит. Не забудьте проверить это локально с включенной отладкой
Код требует как минимум PHP 5.3, любая версия ниже 5.3 вызовет фатальную ошибку. Обратите внимание, что если вы все еще используете любую версию ниже PHP 5.5, вы должны были уже давно обновиться
Измените код и используйте его по своему усмотрению в соответствии с вашими потребностями
ИДЕЯ ЛАМПОЧКИ:
ЧТО НАМ НУЖНО
Чтобы все заработало, нам понадобится следующее:
Номер текущей просматриваемой страницы
posts_per_pageНабор опции в настройках чтения
изготовленный на заказ offset
Измените $found_postsсвойство запроса, чтобы исправить $max_num_pagesсвойство
Нумерация страниц WP_Queryсводится к очень простым нескольким строкам кода
if ( empty($q['nopaging']) && !$this->is_singular ) {
$page = absint($q['paged']);
if ( !$page )
$page = 1;
// If 'offset' is provided, it takes precedence over 'paged'.
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) ) {
$q['offset'] = absint( $q['offset'] );
$pgstrt = $q['offset'] . ', ';
} else {
$pgstrt = absint( ( $page - 1 ) * $q['posts_per_page'] ) . ', ';
}
$limits = 'LIMIT ' . $pgstrt . $q['posts_per_page'];
}
Что в основном происходит, когда явно установлено смещение, pagedпараметр игнорируется. Первый параметр предложения SQL LIMITпересчитывается из смещения и будет количеством сообщений, которые будут пропущены в сгенерированном запросе SQL.
Исходя из вашего вопроса, очевидно, при установке offsetна 0, запрос на смещение не выполняется, что странно, так как следующая проверка должна вернуть true
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) )
0является действительным числом и должно возвращать true. Если это не в вашей установке, вы должны отладить проблему
Чтобы вернуться к данной проблеме, мы будем использовать ту же логику для вычисления и установки нашего смещения, чтобы получить сообщение 1 на странице 2 и оттуда разбить запрос на страницы. Для первой страницы мы не будем ничего менять, поэтому посты, которые, как предполагается, должны быть на странице 1, все еще будут на странице как обычно, нам просто нужно будет позже «спрятать» их, чтобы мы не отображали их на странице 1
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$current_page = $q->get( 'paged' ); // Get the current page number
// We will only need to run this from page 2 onwards
if ( $current_page != 0 ) { // You can also use if ( is_paged() ) {
// Get the amount of posts per page
$posts_per_page = get_option( 'posts_per_page' );
// Recalculate our offset
$offset = ( ( $current_page - 1) * $posts_per_page ) - $posts_per_page; // This should work on page 2 where it returns 0
// Set our offset
$q->set( 'offset', $offset );
}
}
});
Вы должны видеть те же сообщения со страницы 1 на странице 2. Как я уже говорил ранее, если этого не происходит, либо is_numeric( 0 )возвращается false ( чего не должно ), либо у вас есть другое pre_get_postsдействие, которое также пытается установить смещение, или вы используют использование posts_*фильтров предложений ( точнее, post_limitsфильтра ). Это будет то, что вам нужно будет отладить самостоятельно.
Следующая проблема заключается в исправлении нумерации страниц, поскольку, как я уже говорил, у вас будет короткая страница. Для этого нам нужно будет добавить значение get_option( 'posts_per_page' )к количеству сообщений, найденных в запросе, поскольку мы компенсируем запрос на эту сумму. делая это, мы эффективно добавляем 1в $max_num_pagesсобственность.
add_action( 'found_posts', function ( $found_posts, $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$found_posts = $found_posts + get_option( 'posts_per_page');
}
}, 10, 2 );
Это должно отсортировать все, кроме первой страницы.
ВСЕ ВМЕСТЕ СЕЙЧАС ( и специально для @ialocin - Желтая подводная лодка )
Это все должно идти в functions.php
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$current_page = $q->get( 'paged' ); // Get the current page number
// We will only need to run this from page 2 onwards
if ( $current_page != 0 ) { // You can also use if ( is_paged() ) {
// Get the amount of posts per page
$posts_per_page = get_option( 'posts_per_page' );
// Recalculate our offset
$offset = ( ( $current_page - 1) * $posts_per_page ) - $posts_per_page; // This should work on page 2 where it returns 0
// Set our offset
$q->set( 'offset', $offset );
}
}
});
add_filter( 'found_posts', function ( $found_posts, $q )
{
if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT
&& $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT
&& $q->is_cateory( 'news' ) // Only target the news category
) {
$found_posts = $found_posts + get_option( 'posts_per_page');
}
return $found_posts;
}, 10, 2 );
ВАРИАНТЫ ПЕРВОЙ СТРАНИЦЫ
Здесь есть несколько вариантов:
ОПЦИЯ 1
Скорее всего, я бы пошел на этот вариант. То, что вы хотели бы сделать здесь, это создать category-news.php( если вы еще этого не сделали ). Это будет шаблон, который будет использоваться при newsпросмотре категории. Этот шаблон будет очень просто
пример
<?php
get_header()
if ( !is_paged() ) { // This is the first page
get_template_part( 'news', 'special' );
} else { // This is not the first page
get_template_part( 'news', 'loop' );
}
get_sidebar();
get_footer();
Как видите, я включил две части шаблона, news-special.phpи news-loop.php. Основы двух пользовательских шаблонов:
news-special.php-> Эта часть шаблона будет тем, что вы хотите отобразить на первой странице. Добавьте всю свою пользовательскую статическую информацию здесь. Будьте очень осторожны, чтобы не вызывать цикл в этом шаблоне, так как при этом будут отображаться сообщения первой страницы.
news-loop.php-> Это шаблон, где мы будем вызывать цикл. Этот раздел будет выглядеть примерно так:
global $wp_query;
while ( have_posts() ) {
the_post();
// Your template tags and markup
}
ВАРИАНТ 2
Создайте отдельный шаблон со своим статическим содержимым и просто используйте category_templateфильтр, чтобы использовать этот шаблон, когда мы просматриваем первую страницу newsкатегории. Также убедитесь, что в этом шаблоне не вызывается цикл по умолчанию. Кроме того, убедитесь, что ваше соглашение об именах не противоречит именам шаблонов в иерархии шаблонов.
Я надеюсь, что это полезно. Не стесняйтесь терпеть комментарии с проблемами
РЕДАКТИРОВАТЬ
Благодаря OP, в WP_Queryклассе есть определенная ошибка , проверьте trac ticket # 34060 . Код, который я разместил, взят из Wordpress v4.4, и ошибка исправлена в этой версии.
Я вернулся к исходному коду v4.3, где есть ошибка, и я могу подтвердить, что 0игнорируется, когда устанавливается значение в offsetкачестве, поскольку код просто проверяет, offsetявляется ли параметр empty. 0считается пустым в PHP. Я не уверен, что это поведение (ошибка) встречается только в v4.3 или во всех предыдущих версиях (согласно заявке, эта ошибка есть в v4.3), но есть патч для этой ошибки, который вы можете проверить в трак билет. Как я уже сказал, эта ошибка определенно исправлена в v4.4
return $found_posts;после оператора if в действии found_posts. Спасибо!