Как исправить разбиение на страницы для пользовательских циклов?
Я добавил пользовательский /вторичный запрос к шаблону шаблона /настраиваемому шаблону страницы; как я могу заставить WordPress использовать свой пользовательский запрос для разбивки на страницы, вместо того, чтобы использовать разбиение на страницы основного запроса?
Добавление
Я изменил основной запрос цикла с помощью query_posts ()
. Почему не работает pagination, и как я могу исправить это?
5 ответов
Проблема
По умолчанию в любом контексте WordPress использует основной запрос для определения разбивки на страницы. Основной объект запроса хранится в глобальном файле $ wp_query
, который также используется для вывода основного цикла запроса:
if (has_posts ()): while (has_posts ()): the_post ();
Когда вы используете пользовательский запрос , вы создаете полностью отдельный объект запроса:
$ custom_query = new WP_Query ($ custom_query_args);
И этот запрос выводится через совершенно отдельный цикл:
if ($ custom_query-> have_posts ()):
while ($ custom_query-> have_posts ()):
$ Custom_query- > the_post ();
Но теги шаблонов страниц, в том числе previous_posts_link ()
, < a href = "http://codex.wordpress.org/Function_Reference/next_posts_link" rel = "noreferrer"> next_posts_link ()
, posts_nav_link ()
и paginate_links ()
, основывайте свой вывод на главном объекте , $ wp_query
. Этот основной запрос может быть или не быть разбит на страницы. Если текущий контекст является настраиваемым шаблоном страницы, например, основной объект $ wp_query
будет состоять только из одиночного сообщения - идентификатора идентификатора страницы, на который настраивается шаблон настраиваемой страницы.
Если текущий контекст является некоторым архивным индексом, основной $ wp_query
может состоять из достаточно сообщений, чтобы вызвать разбиение на страницы, что приводит к следующей части проблемы: для основного <кода > $ wp_query, WordPress передаст запрос paged
, на основе переменной запроса URL-кода paged
. Когда запрос будет извлечен, этот параметр paged
будет использоваться для определения того, какой набор paginated posts для возврата. Если щелкнуть отображаемую ссылку на страницы и загрузить следующую страницу, , ваш пользовательский запрос не сможет каким-либо образом узнать, что постраничная страница изменилась .
Решение
Передача правильного выгружаемого параметра в пользовательский запрос
Предполагая, что пользовательский запрос использует массив args:
$ custom_query_args = array (
//Параметры пользовательского запроса идут здесь
);
Вам нужно будет передать правильный массив paged
в массив. Вы можете сделать это, извлекая переменную запроса URL, используемую для определения текущей страницы, через get_query_var ()
:
get_query_var ('paged');
Затем вы можете добавить этот параметр в свой собственный массив аргументов запроса:
$ custom_query_args ['paged'] = get_query_var ('paged')
? get_query_var ('paged')
: 1;
Примечание. Если ваша страница является статической главной страницей , обязательно используйте page
вместо paged
поскольку статическая передняя страница использует page
, а не paged
. Это то, что вам нужно для статической главной страницы
$ custom_query_args ['paged'] = get_query_var ('page')
? get_query_var ('page')
: 1;
Теперь, когда пользовательский запрос будет извлечен, будет возвращен правильный набор текстовых сообщений.
Использование пользовательского объекта запроса для разбиения на страницы
Чтобы функции разбиения на страницы отображали правильный результат, т. е. предыдущие /следующие /страницы, связанные с пользовательским запросом - WordPress необходимо принудительно распознавать пользовательский запрос. Для этого требуется немного «взломать»: заменив основной объект $ wp_query
на пользовательский объект запроса, $ custom_query
:
Взломать основной объект запроса
- Резервное копирование основного объекта запроса:
$ temp_query = $ wp_query
- Null главный объект запроса:
$ wp_query = NULL;
-
Сменить пользовательский запрос в основной объект запроса:
$ wp_query = $ custom_query;
$ temp_query = $ wp_query; $ wp_query = NULL; $ wp_query = $ custom_query;
Этот «взлом» должен выполняться перед вызовом каких-либо функций разбиения на страницы
Сбросить основной объект запроса
Как только функции разбиения на страницы выведены, сбросьте основной объект запроса:
$ wp_query = NULL;
$ wp_query = $ temp_query;
Исправления функции разбиения на страницы
Функция previous_posts_link ()
будет работать нормально, независимо от того, нумерацией страниц. Он просто определяет текущую страницу, а затем выводит ссылку на page - 1
.Тем не менее, исправление требуется для next_posts_link ()
для корректного вывода. Это связано с тем, что next_posts_link ()
использует max_num_pages
:
<? php next_posts_link ($ label, $ max_pages); ? >
Как и в случае с другими параметрами запроса, по умолчанию функция будет использовать max_num_pages
для основного объекта $ wp_query
. Чтобы заставить next_posts_link ()
ответить на $ custom_query
, вам необходимо передать max_num_pages
в функцию. Вы можете получить это значение из объекта $ custom_query
: $ custom_query-> max_num_pages
:
<? php next_posts_link ('Старые сообщения', $ custom_query-> max_num_pages); ? >
Объединяя все это
Ниже приведена базовая конструкция настраиваемого цикла запросов с правильно функционирующими функциями разбиения на страницы:
//Определение пользовательских параметров запроса
$ custom_query_args = array (/* Параметры идут сюда * /);
//Получить текущую страницу и добавить к настраиваемому массиву параметров запроса
$ custom_query_args ['paged'] = get_query_var ('paged')? get_query_var ('paged'): 1;
//Создание пользовательского запроса
$ custom_query = новый WP_Query ($ custom_query_args);
//Фиксация пагинации
$ temp_query = $ wp_query;
$ wp_query = NULL;
$ wp_query = $ custom_query;
//Вывод настраиваемого цикла запроса
if ($ custom_query-> have_posts ()):
while ($ custom_query-> have_posts ()):
$ Custom_query- > the_post ();
//Выход цикла происходит здесь
ENDWHILE;
ENDIF;
//Сброс postdata
wp_reset_postdata ();
//Пользовательская разбивка цепочки запросов
previous_posts_link («Старые записи»);
next_posts_link ('Новые сообщения', $ custom_query-> max_num_pages);
//Сброс основного объекта запроса
$ wp_query = NULL;
$ wp_query = $ temp_query;
Добавление: Что о query_posts ()
?
query_posts ()
для вторичных циклов
Если вы используете query_posts ()
для вывода пользовательский цикл, а не создание экземпляра отдельного объекта для пользовательского запроса через WP_Query ()
, то вы _doing_it_wrong ()
, и столкнется с несколькими проблемами (а не наименьшее , из которых будут проблемы с разбивкой по страницам). Первым шагом к решению этих проблем будет преобразование неправильного использования query_posts ()
для надлежащего вызова WP_Query ()
.
Использование query_posts ()
для изменения основного цикла
Если вы просто хотите изменить параметры для запроса основного цикла - например, изменение постов на странице или исключение категории - возможно, у вас возникнет соблазн использовать query_posts ()
. Но вы все равно не должны. Когда вы используете query_posts ()
, вы вынуждаете WordPress замените основной объект запроса. (WordPress фактически выполняет второй запрос и перезаписывает $ wp_query
). Однако проблема заключается в том, что эта замена слишком поздно в процессе обновления страницы.
Решение состоит в фильтрации основного запроса до того, как сообщения будут извлечены , с помощью pre_get_posts
.
Вместо добавления этого в файл шаблона категории (category.php
):
query_posts (массив (
'posts_per_page' => 5
));
Добавьте следующий код в functions.php
:
функция wpse120407_pre_get_posts ($ query) {
//Тест индекса индекса категории
//и убедитесь, что запрос является основным запросом
//а не вторичный запрос (например, навигационное меню
//или последние выпуски виджетов сообщений и т. д.
if (is_category () & & $ query-> is_main_query ()) {
//Изменить сообщения на страницу
$ query-> set ('posts_per_page', 5);
}
}
add_action ('pre_get_posts', 'wpse120407_pre_get_posts');
Вместо добавления этого в файл шаблона индекса сообщений блога (home.php
):
query_posts (массив (
'cat' => '-5'
));
Добавьте следующий код в functions.php
:
функцияwpse120407_pre_get_posts ($ query) {
//Тест для основного индекса сообщений блога
//и убедитесь, что запрос является основным запросом
//а не вторичный запрос (например, навигационное меню
//или последние выпуски виджетов сообщений и т. д.
if (is_home () & & $ query-> is_main_query ()) {
//Исключить категорию ID 5
$ query-> set ('category__not_in', array (5));
}
}
add_action ('pre_get_posts', 'wpse120407_pre_get_posts');
Таким образом, WordPress будет использовать уже измененный объект $ wp_query
при определении разбивки на страницы, без необходимости изменения шаблона.
Когда использовать какую функцию
Исследование этот вопрос и ответьте и это вопрос и ответ , чтобы понять, как и когда использовать WP_Query
, pre_get_posts
и query_posts ()
.
Я использую этот код для настраиваемого цикла с разбивкой на страницы:
& л;? PHP
if (get_query_var ('paged')) {
$ paged = get_query_var ('paged');
} elseif (get_query_var ('page')) {//'page' используется вместо 'paged' на странице Static Front
$ paged = get_query_var ('page');
} else {
$ paged = 1;
}
$ custom_query_args = массив (
'post_type' => 'после',
'posts_per_page' => get_option ( 'posts_per_page'),
'paged' => $ Выгружаемого,
'post_status' => 'публиковать',
'ignore_sticky_posts' => правда,
//'category_name' => 'Заказ кота,
'order' => 'DESC', //'ASC'
'orderby' => 'date' //изменено | название | имя | ID | рант
);
$ custom_query = новый WP_Query ($ custom_query_args);
if ($ custom_query-> have_posts ()):
while ($ custom_query-> have_posts ()): $ custom_query-> the_post (); ? >
<article <? php post_class (); ? > >
<h3> <a href = "<php the_permalink ();> & quot; <& phis; the_title (); ? > & Lt; /а > & Lt; /h3 >
<small> <php the_time ('F jS, Y')?> по <php the_author_posts_link ()?> </small>
<div> <php the_excerpt (); ? > & Lt; /дел >
& Lt; /& статья GT;
& Lt;? PHP
ENDWHILE;
? >
<? php if ($ custom_query-> max_num_pages> 1): //пользовательская разбивка на страницы>
& Lt;? PHP
$ orig_query = $ wp_query; //исправление для разбивки на страницы
$ wp_query = $ custom_query;
? >
<nav class = "prev-next-posts">
<div class = "prev-posts-link">
<? php echo get_next_posts_link («Старые записи», $ custom_query-> max_num_pages); ? >
& Lt; /дел >
<div class = "next-posts-link">
<? php echo get_previous_posts_link («Новые записи»); ? >
& Lt; /дел >
& Lt; /нав >
& Lt;? PHP
$ wp_query = $ orig_query; //исправление для разбивки на страницы
? >
<? php endif; ? >
& Lt;? PHP
wp_reset_postdata (); //сброс запроса
еще:
echo '<p>' .__ ('Извините, никакие сообщения не соответствовали вашим критериям.'). '</p>';
ENDIF;
? >
Источник:
Удивительный, как всегда, Чип. В качестве дополнения к этому рассмотрите ситуацию, когда вы используете шаблон глобальной страницы, прикрепленный к странице, для некоторого «вводного текста», а за ним следует подзапрос, который вы хотите выгрузить.
Используя paginate_links () , как вы упомянули выше, в основном по умолчанию, (и предполагая, что вы у вас есть довольно постоянные ссылки), ваши ссылки на страницы будут по умолчанию равны mysite.ca/page-slug/page /#
, которые прекрасны, но будут бросать ошибки 404
, потому что WordPress не делает знать об этой конкретной структуре URL-адреса и фактически искать дочернюю страницу «страницы», которая является дочерней страницей «page-slug».
Трюк здесь заключается в том, чтобы вставить правильное правило перезаписи, которое применяется только к этой странице «страница псевдостраничной страницы», которая принимает структуру /page /# /
и переписывает ее в строку запроса, которая WordPress МОЖЕТ понять, а именно mysite.ca/?pagename=page-slug&paged = #
. Примечание pagename
и paged
not name
и page
(что вызвало у меня буквально ЧАСЫ горя, мотивируя этот ответ здесь! ).
Вот правило перенаправления:
add_rewrite_rule ("page-slug /page /([0-9] {1,}) /? $", 'index.php? pagename = page-slug & paged = $ matches [1]' , "Вверх" );
Как всегда, при изменении правил перезаписи помните снимите свои постоянные ссылки , посетив Настройки> Постоянная ссылка в интерфейсе администратора.
Если у вас есть несколько страниц, которые будут вести себя таким образом (например, при работе с несколькими настраиваемыми типами сообщений), вам может потребоваться избежать создания нового правила перезаписи для каждого пула страниц. Мы можем написать более общее регулярное выражение, которое работает для любого идентификатора страницы, который вы идентифицируете.
Ниже приведен один подход:
function wpse_120407_pseudo_archive_rewrite () {
//Добавьте пули страниц, которые используют Глобальный шаблон, чтобы имитировать страницу «Архив»
$ pseudo_archive_pages = массив (
«все-кино»,
«все-актеры»
);
$ slug_clause = implode ("|", $ pseudo_archive_pages);
add_rewrite_rule ("($ slug_clause) /page /([0-9] {1,}) /? $", 'index.php? pagename = $ matches [1] & paged = $ matches [2]', Вверх" );
}
add_action ('init', 'wpse_120407_pseudo_archive_rewrite');
Недостатки /Предостережения
Один из недостатков такого подхода, который заставляет меня погладить во рту, - это жесткое кодирование пули страницы. Если администратор когда-либо изменяет страницу на странице псевдо-архива, вы будете тост - правило перезаписи больше не будет соответствовать, и вы получите страшный 404.
Я не уверен, что могу подумать об обходном пути для этого метода, но было бы неплохо, если бы это был шаблон глобальной страницы, который каким-то образом вызвал правило перезаписи. Когда-нибудь я смогу вернуться к этому ответу, если никто другой не сломал этот конкретный орех.
Я изменил основной запрос цикла с помощью
query_posts ()
. Почему не работает постраничная разбивка, и как ее исправить?
Великий ответ Созданный чип должен быть изменен сегодня.
В течение некоторого времени у нас есть переменная $ wp_the_query
, которая должна быть равна глобальному $ wp_query
сразу после выполнения основного запроса.
Вот почему это часть ответа Чипа:
Взломать основной объект запроса
больше не требуется. Мы можем забыть эту часть с созданием временной переменной.
//Фиксация пагинации
$ temp_query = $ wp_query;
$ wp_query = NULL;
$ wp_query = $ custom_query;
Итак, теперь мы можем позвонить:
$ wp_query = $ wp_the_query;
или даже лучше, мы можем позвонить:
wp_reset_query ();
Все остальные чипы указаны.
После этой части запроса-сброса вы можете вызвать функции разбиения на страницы, которые являются f ($ wp_query)
, â € ", они зависят от глобального кода $ wp_query
.
Чтобы еще больше улучшить механику разбиения на страницы и предоставить больше свободы функции query_posts
, я создал это возможное улучшение:
глобальный $ wp_query;
$ paged = get_query_var ('paged', 1);
$ args = array (
'post_type' => '{Your_post_type_name}',
'meta_query' => array ('{добавить аргумент мета запроса в случае необходимости}'),
'orderby' => «Модифицированный»,
'order' => 'DESC',
'posts_per_page' => 20,
'paged' => $ выгружаемого
);
$ query = new WP_Query ($ args);
если ($ query- > have_posts ()):
while ($ query-> have_posts ()): $ query-> the_post ();
//добавьте свой код здесь
ENDWHILE;
wp_reset_query ();
//управлять разбиением на страницы на основе пользовательского запроса.
$ GLOBALS ['wp_query'] -> max_num_pages = $ query-> max_num_pages;
the_posts_pagination (массив (
'mid_size' => 1,
'prev_text' => __ ('Предыдущая страница', 'patelextensions'),
'next_text' => __ ('Следующая страница', 'patelextensions'),
'before_page_number' => '<span class = "meta-nav screen-reader-text">' , __ ('Страница', 'patelextensions'). '</span>',
));
еще:
? >
<div class = "text-center контейнера" > <php echo _d ('Результат не найден', '30'); ? > & Lt; /дел >
& Lt;? PHP
ENDIF;
? >