我已经在模板文件/自定义页面模板中添加了自定义/辅助查询;如何使WordPress使用我的自定义查询进行分页,而不是使用主查询循环的分页?
附录
我已经通过修改了主循环查询query_posts()。为什么分页不起作用,如何解决?
我已经在模板文件/自定义页面模板中添加了自定义/辅助查询;如何使WordPress使用我的自定义查询进行分页,而不是使用主查询循环的分页?
我已经通过修改了主循环查询query_posts()。为什么分页不起作用,如何解决?
Answers:
默认情况下,在任何给定的上下文中,WordPress都会使用主查询来确定分页。主查询对象存储在$wp_query全局对象中,该对象也用于输出主查询循环:
if ( have_posts() ) : while ( have_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(),next_posts_link(),posts_nav_link(),和paginate_links(),根据他们的输出主要查询对象,$wp_query。该主查询可以分页,也可以不分页。例如,如果当前上下文是自定义页面模板,则主要$wp_query对象将仅包含一个帖子 -自定义页面模板所分配到的页面ID的帖子。
如果当前上下文是某种存档索引,则主要内容$wp_query可能包含足以引起分页的帖子,这将导致问题的下一部分:对于主要$wp_query对象,WordPress将paged 基于以下内容将参数传递给查询:pagedURL查询变量。提取查询后,该paged参数将用于确定要返回的一组分页帖子。如果单击了显示的分页链接,并加载了下一页,则您的自定义查询将无法知道分页已更改。
假设自定义查询使用args数组:
$custom_query_args = array(
// Custom query parameters go here
);
您将需要将正确的paged参数传递给数组。您可以通过以下方法获取用于确定当前页面的URL查询变量get_query_var():
get_query_var( 'paged' );
然后,您可以将该参数附加到自定义查询args数组中:
$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识别自定义查询。这需要一点“ hack”:用$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;
必须在调用任何分页功能之前完成此“ hack”操作
一旦输出了分页功能,就重置主查询对象:
$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()用于输出自定义循环,而不是通过实例化自定义查询的单独对象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( 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在确定分页时使用已修改的对象,而无需修改模板。
研究这个问题,并回答与这个问题和答案,以了解如何以及何时使用WP_Query,pre_get_posts和query_posts()。
paged没有更新(观察到与admin-有关ajax.php环境),所以我添加了它: global $paged; $paged = $custom_query_args['paged']; 并且起作用了:)
我将此代码用于带有分页的自定义循环:
<?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;
?>
资源:
一如既往的酷。作为对此的附录,请考虑以下情况:您正在使用连接到页面的全局页面模板作为“介绍文字”,并在其后跟要分页的子查询。
如上文所述,使用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这确实使我悲伤了HOURS,在此激励了这个答案!)。
这是重定向规则:
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' );
这种方法的缺点是让Page slug硬编码,这使我有些p嘴。如果管理员更改了该伪归档页面的页面标签,那么您将敬酒-重写规则将不再匹配,您将获得可怕的404。
我不确定是否可以考虑此方法的解决方法,但是如果是全局页面模板以某种方式触发了重写规则,那将是很好的。有一天,如果没有其他人能破解那个特定的螺母,我可能会重新审视这个答案。
_wp_page_template,然后添加另一个重写和刷新规则。
我已经通过修改了主循环查询
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();
Chip概述的所有其他内容均会保留。在查询重置部分之后,您可以调用分页函数,f($wp_query)它们取决于$wp_query全局。
为了进一步改善分页机制并赋予query_posts功能更多的自由,我创建了以下可能的改进:
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;
?>