Как исправить разбиение на страницы для пользовательских циклов?
4 ответ
- голосов
-
- 2015-11-09
Я использую этот код для пользовательского цикла с разбивкой на страницы:
<?php if ( get_query_var('paged') ) { $paged = get_query_var('paged'); } elseif ( get_query_var('page') ) { // 'page' is used instead of 'paged' on Static Front Page $paged = get_query_var('page'); } else { $paged = 1; } $custom_query_args = array( 'post_type' => 'post', 'posts_per_page' => get_option('posts_per_page'), 'paged' => $paged, 'post_status' => 'publish', 'ignore_sticky_posts' => true, //'category_name' => 'custom-cat', 'order' => 'DESC', // 'ASC' 'orderby' => 'date' // modified | title | name | ID | rand ); $custom_query = new 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(); ?>"><?php the_title(); ?></a></h3> <small><?php the_time('F jS, Y') ?> by <?php the_author_posts_link() ?></small> <div><?php the_excerpt(); ?></div> </article> <?php endwhile; ?> <?php if ($custom_query->max_num_pages > 1) : // custom pagination ?> <?php $orig_query = $wp_query; // fix for pagination to work $wp_query = $custom_query; ?> <nav class="prev-next-posts"> <div class="prev-posts-link"> <?php echo get_next_posts_link( 'Older Entries', $custom_query->max_num_pages ); ?> </div> <div class="next-posts-link"> <?php echo get_previous_posts_link( 'Newer Entries' ); ?> </div> </nav> <?php $wp_query = $orig_query; // fix for pagination to work ?> <?php endif; ?> <?php wp_reset_postdata(); // reset the query else: echo '<p>'.__('Sorry, no posts matched your criteria.').'</p>'; endif; ?>
Источник:
I use this code for custom loop with pagination:
<?php if ( get_query_var('paged') ) { $paged = get_query_var('paged'); } elseif ( get_query_var('page') ) { // 'page' is used instead of 'paged' on Static Front Page $paged = get_query_var('page'); } else { $paged = 1; } $custom_query_args = array( 'post_type' => 'post', 'posts_per_page' => get_option('posts_per_page'), 'paged' => $paged, 'post_status' => 'publish', 'ignore_sticky_posts' => true, //'category_name' => 'custom-cat', 'order' => 'DESC', // 'ASC' 'orderby' => 'date' // modified | title | name | ID | rand ); $custom_query = new 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(); ?>"><?php the_title(); ?></a></h3> <small><?php the_time('F jS, Y') ?> by <?php the_author_posts_link() ?></small> <div><?php the_excerpt(); ?></div> </article> <?php endwhile; ?> <?php if ($custom_query->max_num_pages > 1) : // custom pagination ?> <?php $orig_query = $wp_query; // fix for pagination to work $wp_query = $custom_query; ?> <nav class="prev-next-posts"> <div class="prev-posts-link"> <?php echo get_next_posts_link( 'Older Entries', $custom_query->max_num_pages ); ?> </div> <div class="next-posts-link"> <?php echo get_previous_posts_link( 'Newer Entries' ); ?> </div> </nav> <?php $wp_query = $orig_query; // fix for pagination to work ?> <?php endif; ?> <?php wp_reset_postdata(); // reset the query else: echo '<p>'.__('Sorry, no posts matched your criteria.').'</p>'; endif; ?>
Source:
-
- 2016-12-17
Шикарный как всегда Чип. В качестве дополнения к этому рассмотрим ситуацию,когда вы используете глобальный шаблон страницы,прикрепленный к странице для некоторого «вступительного текста»,и за ним следует подзапрос,который вы хотите вывести на страницы.
Использование paginate_links () ,как вы упомянули выше,с в основном значениями по умолчанию (и при условии,что у вас есть включены красивые постоянные ссылки) для ваших ссылок на страницы по умолчанию будет использоваться
mysite.ca/page-slug/page/#
,что прекрасно,но вызовет ошибки404
,потому что WordPress не знает об этой конкретной структуре URL-адреса и фактически будет искать дочернюю страницу "page",которая является дочерней для "page-slug".Хитрость заключается в том,чтобы вставить отличное правило перезаписи,которое применяется только к той конкретной "странице псевдоархива",которая принимает структуру
/page/#/
и переписывает ее в строку запроса,которая WordPress МОЖЕТ понять,а именноmysite.ca/?pagename=page-slug&paged=#
. Обратите внимание наpagename
иpaged
,а не наname
иpage
(которые вызвали у меня буквально ЧАСЫ горя,мотивируя этот ответ здесь! ).Вот правило перенаправления:
add_rewrite_rule( "page-slug/page/([0-9]{1,})/?$", 'index.php?pagename=page-slug&paged=$matches[1]', "top" );
Как всегда,при изменении правил перезаписи не забудьте очистить свои постоянные ссылки ,перейдя в Настройки> Постоянные ссылки в административной части.
Если у вас есть несколько страниц,которые будут вести себя подобным образом (например,при работе с несколькими настраиваемыми типами сообщений),вы можете избежать создания нового правила перезаписи для каждого ярлыка страницы. Мы можем написать более общее регулярное выражение,которое будет работать для любого идентифицированного вами ярлыка страницы.
Один из подходов описан ниже:
function wpse_120407_pseudo_archive_rewrite(){ // Add the slugs of the pages that are using a Global Template to simulate being an "archive" page $pseudo_archive_pages = array( "all-movies", "all-actors" ); $slug_clause = implode( "|", $pseudo_archive_pages ); add_rewrite_rule( "($slug_clause)/page/([0-9]{1,})/?$", 'index.php?pagename=$matches[1]&paged=$matches[2]', "top" ); } add_action( 'init', 'wpse_120407_pseudo_archive_rewrite' );
Недостатки/предостережения
Одним из недостатков этого подхода,из-за которого меня немного рвет во рту,является жесткое кодирование заголовка страницы. Если администратор когда-либо изменит заголовок этой страницы псевдоархива,вы тост - правило перезаписи больше не будет соответствовать,и вы получите ужасное 404.
Я не уверен,что могу придумать обходной путь для этого метода,но было бы неплохо,если бы это был глобальный шаблон страницы,который каким-то образом запускал правило перезаписи. Когда-нибудь я могу вернуться к этому ответу,если никто другой не расколол этот конкретный орех.
Awesome as always Chip. As an addendum to this, consider the situation whereby you are using a global page template attached to a Page for some "intro text" and it's followed by a subquery that you want to be paged.
Using paginate_links() as you mention above, with mostly defaults, (and assuming you have pretty permalinks turned on) your pagination links will default to
mysite.ca/page-slug/page/#
which is lovely but will throw404
errors because WordPress doesn't know about that particular URL structure and will actually look for a child page of "page" that's a child of "page-slug".The trick here is to insert a nifty rewrite rule that only applies to that particular "pseudo archive page" page slug that accepts the
/page/#/
structure and rewrites it to a query string that WordPress CAN understand, namelymysite.ca/?pagename=page-slug&paged=#
. Notepagename
andpaged
notname
andpage
(which caused me literally HOURS of grief, motivating this answer here!).Here's the redirect rule:
add_rewrite_rule( "page-slug/page/([0-9]{1,})/?$", 'index.php?pagename=page-slug&paged=$matches[1]', "top" );
As always, when changing rewrite rules, remember to flush your permalinks by visiting Settings > Permalinks in the Admin back-end.
If you have multiple pages that are going to behave this way (for example, when dealing with multiple custom post types), you might want to avoid creating a new rewrite rule for each page slug. We can write a more generic regular expression that works for any page slug you identify.
One approach is below:
function wpse_120407_pseudo_archive_rewrite(){ // Add the slugs of the pages that are using a Global Template to simulate being an "archive" page $pseudo_archive_pages = array( "all-movies", "all-actors" ); $slug_clause = implode( "|", $pseudo_archive_pages ); add_rewrite_rule( "($slug_clause)/page/([0-9]{1,})/?$", 'index.php?pagename=$matches[1]&paged=$matches[2]', "top" ); } add_action( 'init', 'wpse_120407_pseudo_archive_rewrite' );
Disadvantages / Caveats
One disadvantage of this approach that makes me puke in my mouth a little is the hard-coding of the Page slug. If an admin ever changes the page slug of that pseudo-archive page, you're toast - the rewrite rule will no longer match and you'll get the dreaded 404.
I'm not sure I can think of a workaround for this method, but it would be nice if it were the global page template that somehow triggered the rewrite rule. Some day I may revisit this answer if no one else has cracked that particular nut.
-
Вы можете подключить сохранение публикации,проверить,есть ли на странице ваш шаблон архива под мета-ключом `_wp_page_template`,а затем добавить другие правила перезаписи и сброса.You could hook post save, check if the page has your archive template under the meta key `_wp_page_template`, then add another rewrite and flush rules.
- 1
- 2016-12-17
- Milo
-
- 2017-01-13
<цитата>Я изменил запрос основного цикла с помощью
query_posts()
. Почему не работает разбивка на страницы и как это исправить?Отличный ответ. Созданный чип нужно изменить сегодня.
Некоторое время у нас есть переменная$wp_the_query
,которая должна быть равна глобальной$wp_query
сразу после выполнения основного запроса.Вот почему это часть из ответа Чипа:
<цитата>Взломать основной объект запроса
больше не нужен. Мы можем забыть об этой части,создав временную переменную.
// Pagination fix $temp_query = $wp_query; $wp_query = NULL; $wp_query = $custom_query;
Итак,теперь мы можем позвонить:
$wp_query = $wp_the_query;
или еще лучше мы можем позвонить:
wp_reset_query();
Все,что указал Чип,остается. После этой части сброса запроса вы можете вызвать функции разбиения на страницы,которые являются
<час/>f($wp_query)
,- они зависят от$wp_query
global.Для дальнейшего улучшения механики разбивки на страницы и предоставления большей свободы функции
query_posts
я создал следующее возможное улучшение:I have modified the main loop query via
query_posts()
. Why isn't pagination working, and how do I fix it?Great answer Chip created needs to be modified today.
For some time we have$wp_the_query
variable that should be equal to the$wp_query
global just after the main query executes.This is why this the part from the Chip's answer:
Hack the main query object
is not needed anymore. We can forget this part with creating the temporary variable.
// Pagination fix $temp_query = $wp_query; $wp_query = NULL; $wp_query = $custom_query;
So now we can call:
$wp_query = $wp_the_query;
or even better we can call:
wp_reset_query();
Everything other Chip outlined stays. After that query-reset-part you can call the pagination functions that are
f($wp_query)
, — they depend on$wp_query
global.
In order to further improve the pagination mechanics and to give more freedom to the
query_posts
function I created this possible improvement: -
- 2018-03-06
global $wp_query; $paged = get_query_var('paged', 1); $args = array( 'post_type' => '{your_post_type_name}', 'meta_query' => array('{add your meta query argument if need}'), 'orderby' => 'modified', 'order' => 'DESC', 'posts_per_page' => 20, 'paged' => $paged ); $query = new WP_Query($args); if($query->have_posts()): while ($query->have_posts()) : $query->the_post(); //add your code here endwhile; wp_reset_query(); //manage pagination based on custom Query. $GLOBALS['wp_query']->max_num_pages = $query->max_num_pages; the_posts_pagination(array( 'mid_size' => 1, 'prev_text' => __('Previous page', 'patelextensions'), 'next_text' => __('Next page', 'patelextensions'), 'before_page_number' => '<span class="meta-nav screen-reader-text">' . __('Page', 'patelextensions') . ' </span>', )); else: ?> <div class="container text-center"><?php echo _d('Result not found','30'); ?></div> <?php endif; ?>
global $wp_query; $paged = get_query_var('paged', 1); $args = array( 'post_type' => '{your_post_type_name}', 'meta_query' => array('{add your meta query argument if need}'), 'orderby' => 'modified', 'order' => 'DESC', 'posts_per_page' => 20, 'paged' => $paged ); $query = new WP_Query($args); if($query->have_posts()): while ($query->have_posts()) : $query->the_post(); //add your code here endwhile; wp_reset_query(); //manage pagination based on custom Query. $GLOBALS['wp_query']->max_num_pages = $query->max_num_pages; the_posts_pagination(array( 'mid_size' => 1, 'prev_text' => __('Previous page', 'patelextensions'), 'next_text' => __('Next page', 'patelextensions'), 'before_page_number' => '<span class="meta-nav screen-reader-text">' . __('Page', 'patelextensions') . ' </span>', )); else: ?> <div class="container text-center"><?php echo _d('Result not found','30'); ?></div> <?php endif; ?>
Я добавил настраиваемый/вторичный запрос в файл шаблона/шаблон настраиваемой страницы;как я могу заставить WordPress использовать мой собственный запрос для разбивки на страницы вместо использования разбиения на страницы основного цикла запроса?
Дополнение
Я изменил запрос основного цикла с помощью
query_posts()
.Почему не работает разбивка на страницы и как это исправить?