用 WP_Query 查文章,永远是三步:
<?php
// 1. 新建查询
$q = new WP_Query( array(
'posts_per_page' => 5,
) );
// 2. 循环
if ( $q->have_posts() ) :
while ( $q->have_posts() ) : $q->the_post(); ?>
<h3><?php the_title(); ?></h3>
<?php endwhile;
endif;
// 3. 恢复
wp_reset_postdata();
?>
就跟主循环一样,只不过:
have_posts() 前面多了 $q->;the_post() 前面多了 $q->;wp_reset_postdata()。为什么前面要加 $q->?因为你查的是“自己的”查询,不是主查询。主循环不写前缀,是因为它默认操作 $wp_query。
$q->the_post() 会把全局 $post 换成你的文章。循环结束后,$post 停在最后一篇。
这时候如果你后面还要用主查询(比如“当前文章的分类”),读到的就是最后一篇相关文章,不是当前文章——数据全错。
wp_reset_postdata() 的作用就是:把 $post 恢复到主查询的当前位置。
记住一句话:只要用了 new WP_Query 并循环过,结尾就必须 wp_reset_postdata()。
<?php
$latest = new WP_Query( array(
'posts_per_page' => 5,
'ignore_sticky_posts' => 1,
) );
?>
<ul>
<?php while ( $latest->have_posts() ) : $latest->the_post(); ?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; wp_reset_postdata(); ?>
</ul>
就这么点。放在侧栏、页脚、文章底部,都能用。
主循环只查“当前页面该显示的文章”。凡是主循环不包含的,都需要自己查:
一句话:主循环负责“这一页”,WP_Query 负责“额外的”。
ignore_sticky_posts:忽略置顶文章。
如果不加,置顶文章会被强制排在最前面,可能把你精心排的顺序打乱。做侧栏列表、相关文章时,建议都加上。
每 new 一个 WP_Query,就是一次数据库查询。一个页面里别 new 太多个——侧栏 3 个、相关文章 1 个、页脚 1 个,加起来 5 次查询,已经不少了。
如果查询条件固定,可以考虑用 transient 缓存结果(进阶内容,卷六会提)。
一句话记住:new WP_Query → 带 $q-> 的循环 → wp_reset_postdata,三步不能少。
下一篇,把常用参数列成一张速查表。