query_posts 为什么是坏东西

作者: admin 分类: wordpress主题制作教程 发布时间: 2026-11-06 18:30

先看一段熟悉的代码

caogenbj 的 single.php 里,“相关文章”是这么写的:

$args = array(
    'post_status' => 'publish',
    'tag__in' => explode(',', $tags),
    'post__not_in' => explode(',', $exclude_id),
    'posts_per_page' => 10,
);
query_posts($args);
while( have_posts() ) { the_post(); ?>
    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php } wp_reset_query();

这段代码能跑,效果也对。但它用的是 query_posts(),而 WordPress 官方文档里明确写了:不要用 query_posts。

为什么?

query_posts 干了什么

它的名字叫“query posts”,但它干的不是“新查一次”,而是把主查询整个替换掉。

打个比方:主查询是你手里的那本书。query_posts 不是“借另一本书来看看”,而是把你手里这本书直接换成了另一本。换完之后,你原来读到第几页、书签夹在哪,全没了。

具体后果有三个:

后果一:主查询被覆盖

调用 query_posts 之后,全局 $wp_query 变成了新的查询。原来那个“这篇文章”的主查询,没了。

这会导致:

  • 分页错乱(分页是根据主查询算的);
  • 当前文章的上下文丢失(比如 is_single() 可能变味);
  • 如果后面还有代码依赖主查询,全都会读错。

后果二:多查一次数据库

主查询已经查过一次了。你 query_posts 又查一次。一个页面两次查库,白烧性能。

后果三:wp_reset_query 只是“擦屁股”

代码最后那句 wp_reset_query(),是为了把主查询“恢复”回去。但它恢复的只是查询对象,已经浪费的性能、已经被打乱的上下文,回不来。

用 query_posts 再 reset,本质是“先弄坏再修好”,不如一开始就别弄坏。

正确做法:new WP_Query

同样的事,用 WP_Query 写:

$related = new WP_Query( array(
    'post_status' => 'publish',
    'tag__in' => explode(',', $tags),
    'post__not_in' => explode(',', $exclude_id),
    'ignore_sticky_posts' => 1,
    'posts_per_page' => 10,
) );

while ( $related->have_posts() ) {
    $related->the_post(); ?>
    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php }

wp_reset_postdata();

差别在哪:

对比 query_posts new WP_Query
对主查询的影响 覆盖 不影响
数据库查询次数 多一次 多一次(但只查自己)
分页 会被搞乱 不影响
恢复方式 wp_reset_query wp_reset_postdata

关键区别:WP_Query 是一个独立的查询对象,不碰主查询。主查询还在那儿,分页、上下文都不受影响。

注意 wp_reset_postdata 的位置

循环结束后要调 wp_reset_postdata(),因为 $related->the_post() 把全局 $post 改成了相关文章。不恢复的话,后面的代码读到的就是最后一篇相关文章,不是当前文章。

下一篇专门讲这个。

一个容易踩的坑

caogenbj 原来的参数里有个 'caller_get_posts' => 1。这是个已经废弃的参数,WordPress 早就不认了。正确写法是 'ignore_sticky_posts' => 1(忽略置顶文章)。

我把这个也顺手改了。这种废弃参数不报错,只是“写了等于没写”,很容易一直留着。

小结

一句话记住:query_posts 会覆盖主查询,别用;要查文章就用 new WP_Query,查完 wp_reset_postdata。

下一篇,把 WP_Query 的常用参数系统过一遍。

本系列导航

相关文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Powered by 草根站长笔记 © 2015-2026 草根站长笔记 Inc.版权所有,禁止转载