默认情况下,在任何给定的上下文中,WordPress都使用主查询来确定分页。主查询对象存储在$wp_query
global,也用于输出主查询循环:
if ( have_posts() ) : while ( have_posts() ) : the_post();
当你
use a custom query, 您可以创建一个完全独立的查询对象:
$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()
,
next_posts_link()
,
posts_nav_link()
, 和
paginate_links()
, 将其输出基于主查询对象,
$wp_query
. 该主查询可以分页,也可以不分页。如果当前上下文是自定义页面模板,例如,主
$wp_query
对象将只包含一篇文章,即指定自定义页面模板的页面ID。
如果当前上下文是某种存档索引,则主$wp_query
可能由足够多的帖子组成,导致分页,从而导致问题的下一部分:对于main$wp_query
对象,WordPress将传递paged
查询的参数,基于paged
URL查询变量。获取查询时,该paged
参数将用于确定要返回哪一组分页的帖子。如果单击显示的分页链接并加载下一页,则自定义查询将无法知道分页已更改。
假设自定义查询使用args数组,则解决方案将正确的分页参数传递给自定义查询:
$custom_query_args = array(
// Custom query parameters go here
);
您需要通过正确的
paged
数组的参数。您可以通过以下方式获取用于确定当前页面的URL查询变量:
get_query_var()
:
get_query_var( \'paged\' );
然后,可以将该参数附加到自定义查询参数数组中:
$custom_query_args[\'paged\'] = get_query_var( \'paged\' )
? get_query_var( \'paged\' )
: 1;
Note: 如果您的页面是
static front page, 确保使用
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
主查询对象为空:$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( \'Older Posts\' , $custom_query->max_num_pages ); ?>
以下是定制查询循环的基本构造,具有正常运行的分页功能:
// 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;
附录:关于
query_posts()
?
使用query_posts()
要修改主循环,如果您只想修改主循环查询的参数,例如更改每页的帖子或排除类别,您可能会尝试使用query_posts()
. 但你还是不应该。当你使用query_posts()
, 您可以强制WordPress替换主查询对象。(WordPress实际上进行了第二次查询,并覆盖$wp_query
.) 但问题是,它在更新分页的过程中太晚了。
解决方案是通过pre_get_posts
钩
而不是将其添加到类别模板文件中(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\'
) );
将以下内容添加到
functions.php
:
function wpse120407_pre_get_posts( $query ) {
// Test for main blog posts 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_home() && $query->is_main_query() ) {
// Exclude category ID 5
$query->set( \'category__not_in\', array( 5 ) );
}
}
add_action( \'pre_get_posts\', \'wpse120407_pre_get_posts\' );
这样,WordPress将使用已修改的
$wp_query
对象,无需修改模板。