Это довольно интересный вопрос (за который я проголосовал, особенно за ваш подход и исследования ). Большой кривая здесь - первая страница запроса:
Вы не можете настроить запрос на возврат 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. Спасибо!