有次我在文章页底部加“相关文章”,用的 new WP_Query。加完之后,页脚的一句话突然变成了相关文章里最后一篇的标题。
找了半天,发现是漏了 wp_reset_postdata()。
$q->the_post() 会把全局 $post 换成“相关文章里的某一篇”。循环结束后,$post 停在最后一篇。
这时候如果你后面还有代码用 $post——比如页脚的“当前文章标题”、评论区的“本文作者”——读到的全是那篇相关文章,不是当前文章。
wp_reset_postdata() 干的事:把 $post 恢复到主查询的当前位置。
只要满足这两个条件,就必须调:
new WP_Query(或 get_posts 配合 setup_postdata);the_post()(或 setup_postdata())。少一个都不用调(比如只查数量、不循环,就不影响 $post)。
最保险的做法:每次 new WP_Query 的循环结束,无条件加一句 wp_reset_postdata()。加了不会错,不加可能错。
循环结束之后、下一个查询之前:
<?php
$related = new WP_Query( array( /* ... */ ) );
while ( $related->have_posts() ) {
$related->the_post();
/* 输出 */
}
wp_reset_postdata(); // ← 就放这
?>
注意别放在循环里面(每轮都恢复一次,没意义),也别放在 if 分支里(可能不执行)。
这两个名字很像,很多人混用。区别是:
| wp_reset_postdata | wp_reset_query | |
|---|---|---|
| 恢复什么 | 全局 $post |
全局 $wp_query |
| 配合谁用 | new WP_Query |
query_posts |
| 推荐吗 | 推荐 | 不推荐(因为 query_posts 本身不该用) |
简单记:用 new WP_Query → wp_reset_postdata;用 query_posts → wp_reset_query。但后者最好别用。
get_posts() 是另一个查文章的函数,返回数组,不自动设置 $post。所以它本身不会污染全局。
但如果你在循环里调了 setup_postdata( $post ),那就要在结束时 wp_reset_postdata()。规则是一样的:动过 $post,就要恢复。
页面出现“标题对、内容错”“页脚文字变得莫名其妙”这类问题,第一反应就去找:是不是有个 WP_Query 循环没调 wp_reset_postdata?
这个 bug 特别隐蔽,因为页面不报错,只是数据悄悄错了。
一句话记住:new WP_Query 循环结束,必须 wp_reset_postdata;不调的话,后面所有读 $post 的代码都会读到最后一篇“别人的文章”。
卷二到这里结束。你已经掌握了:主循环、$post、WP_Query、pre_get_posts、分页、reset。这些是主题里“查和显示”的全部基础。
卷三开始讲“零件”:head、导航、侧栏、评论、分页、面包屑。这些是把一个页面填满的东西。