附录
我已通过
query_posts()
修改了主循环查询。为什么分页不起作用,该如何解决?#1 楼
问题默认情况下,在任何给定的上下文中,WordPress都会使用主查询来确定分页。主查询对象存储在
$wp_query
全局变量中,该全局变量还用于输出主查询循环:单独的查询对象:if ( have_posts() ) : while ( have_posts() ) : the_post();
,该查询通过完全独立的循环输出:
$custom_query = new WP_Query( $custom_query_args );
但是分页模板标签(包括
previous_posts_link()
,next_posts_link()
,posts_nav_link()
和paginate_links()
)的输出基于主查询对象$wp_query
。该主查询可以分页,也可以不分页。例如,如果当前上下文是自定义页面模板,则主$wp_query
对象将仅包含一个帖子-自定义页面模板所分配到的页面ID的帖子。 如果当前上下文是某种存档索引,则主
$wp_query
可能包含足以引起分页的帖子,这将导致问题的下一部分:对于主$wp_query
对象,WordPress将根据paged
URL查询变量,将paged
参数传递给查询。提取查询后,该paged
参数将用于确定要返回哪一组分页的帖子。如果单击了显示的分页链接,并且加载了下一页,则您的自定义查询将无法知道分页已更改。解决方案
传递自定义查询的正确分页参数
假定自定义查询使用了args数组:
if ( $custom_query->have_posts() ) :
while ( $custom_query->have_posts() ) :
$custom_query->the_post();
您将需要传递正确的
paged
数组的参数。您可以通过get_query_var()
来获取用于确定当前页面的URL查询变量来做到这一点:$custom_query_args = array(
// Custom query parameters go here
);
然后可以将该参数附加到自定义查询args数组中:
get_query_var( 'paged' );
注意:如果您的页面是静态首页,请确保使用
page
而不是paged
,因为静态首页使用page
而不是paged
。这是静态首页应该具有的功能$custom_query_args['paged'] = get_query_var( 'paged' )
? get_query_var( 'paged' )
: 1;
现在,当获取自定义查询时,将返回正确的分页帖子集。 >
对分页功能使用自定义查询对象
为了使分页功能产生正确的输出-即相对于自定义查询的上一页/下一页/页面链接-必须强制WordPress识别自定义查询。这需要一点“ hack”:用自定义查询对象
$wp_query
替换主$custom_query
对象:没有主查询对象
主查询对象:
$temp_query = $wp_query
使主查询对象无效:
$wp_query = NULL;
将自定义查询交换到主查询对象:
$wp_query = $custom_query;
$custom_query_args['paged'] = get_query_var( 'page' )
? get_query_var( 'page' )
: 1;
必须在调用任何分页功能之前完成此“ hack”操作
重置主查询对象
一次分页功能已输出,请重置主查询对象:
$temp_query = $wp_query;
$wp_query = NULL;
$wp_query = $custom_query;
分页功能修复
previous_posts_link()
函数将正常运行,而不考虑分页。它仅确定当前页面,然后输出page - 1
的链接。但是,需要修复才能正确输出next_posts_link()
。这是因为next_posts_link()
使用max_num_pages
参数:$wp_query = NULL;
$wp_query = $temp_query;
与其他查询参数一样,默认情况下该函数将
max_num_pages
用于主要$wp_query
对象。为了强制next_posts_link()
占用$custom_query
对象,您需要将max_num_pages
传递给函数。您可以从$custom_query
对象获取此值:$custom_query->max_num_pages
:<?php next_posts_link( $label , $max_pages ); ?>
将它们全部放在一起
以下是具有适当功能的分页功能的自定义查询循环的基本结构:
<?php next_posts_link( 'Older Posts' , $custom_query->max_num_pages ); ?>
附录:关于
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
)中:// Define custom query parameters
$custom_query_args = array( /* Parameters go here */ );
// Get current page and append to custom query parameters array
$custom_query_args['paged'] = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
// Instantiate custom query
$custom_query = new WP_Query( $custom_query_args );
// Pagination fix
$temp_query = $wp_query;
$wp_query = NULL;
$wp_query = $custom_query;
// Output custom query loop
if ( $custom_query->have_posts() ) :
while ( $custom_query->have_posts() ) :
$custom_query->the_post();
// Loop output goes here
endwhile;
endif;
// Reset postdata
wp_reset_postdata();
// Custom query loop pagination
previous_posts_link( 'Older Posts' );
next_posts_link( 'Newer Posts', $custom_query->max_num_pages );
// Reset main query object
$wp_query = NULL;
$wp_query = $temp_query;
添加跟随
category.php
:query_posts( array(
'posts_per_page' => 5
) );
而不是将其添加到博客文章索引模板文件(
functions.php
)中:function wpse120407_pre_get_posts( $query ) {
// Test for category archive index
// and ensure that the query is the main query
// and not a secondary query (such as a nav menu
// or recent posts widget output, etc.
if ( is_category() && $query->is_main_query() ) {
// Modify posts per page
$query->set( 'posts_per_page', 5 );
}
}
add_action( 'pre_get_posts', 'wpse120407_pre_get_posts' );
将以下内容添加到
home.php
中:query_posts( array(
'cat' => '-5'
) );
这样,WordPress在确定分页时将使用已修改的
functions.php
对象,而无需修改模板。 何时使用什么功能
研究此问题和答案以及此问题和答案,以了解如何以及何时使用
$wp_query
,WP_Query
和pre_get_posts
。#2 楼
我将此代码用于带有分页的自定义循环:<?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;
?>
来源:
带有分页的WordPress自定义循环
#3 楼
一如既往的酷。作为对此的补充,请考虑以下情况:正在使用附加到页面的全局页面模板作为“介绍文字”,然后是要分页的子查询。使用paginate_links ()如上所述,大多数情况下都是默认设置(并且假设您已启用了永久链接),您的分页链接将默认设置为
mysite.ca/page-slug/page/#
,这很可爱,但会抛出404
错误,因为WordPress不知道该特定的URL结构,实际上寻找“ page”的子页面,而“ page-slug”的子页面。这里的技巧是插入一个漂亮的重写规则,该规则仅适用于特定的“ pseudo存档页面”页面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" );
缺点/警告
这种方法的一个缺点是Page slug的硬编码,这使我有些p嘴。如果管理员曾经更改过该伪归档页面的页面标签,那么您将敬酒-重写规则将不再匹配,您将获得可怕的404。
我不确定是否可以考虑此方法的解决方法,但是如果是全局页面模板以某种方式触发了重写规则,那就太好了。有一天,如果没人能破解那个特殊的螺母,我可能会重新审视这个答案。
评论
您可以挂钩保存,检查页面是否在元键_wp_page_template下具有存档模板,然后添加另一个重写和刷新规则。
–米洛
16 Dec 17'0:54
#4 楼
我通过
query_posts()
修改了主循环查询。为什么分页不起作用,我该如何解决?好答案今天创建的芯片需要修改。
一段时间以来,我们有
$wp_the_query
变量应该等于$wp_query
这就是为什么Chip答案中的这部分内容:
不再需要主查询对象
。
br />我们可以通过创建临时变量来忘记这部分。
// 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
全局。为了进一步改善分页机制并为
query_posts
功能赋予更多自由度,我创造了这一可能的改进:https://core.trac.wordpress.org/ticket/39483
#5 楼
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;
?>
评论
抄本中的希望页面可能是如此完整。
–Pieter Goosen
2014年4月3日在12:41
芯片,你让我开心!
–tepkenvannkorn
2014年9月8日在8:57
芯片,您总是可以节省很多时间!如果只有Google会在我疯狂搜索之前给您更高的答案(针对Googlers的标注);)谢谢。
–敏捷的SEO
2014-09-14 15:56
使用您的示例,直到我使用了if-else块(而不是?:有条件的)在此页面下找到该主题之前,我无法使分页正常工作:themeforest.net/forums/thread / ...,非常奇怪。否则,这个答案教给我很多东西。
– P a u l
2014年12月8日下午6:52
很好的答案-1件事,我在ajax调用中运行下一个/上一个帖子链接功能时遇到问题-只是不愿意-快速浏览后发现全局页面没有被更新(与管理员有关) -ajax.php环境),因此我添加了以下内容:global $ paged; $ paged = $ custom_query_args ['paged'];它起作用了:)
–morse
2014年12月20日16:00