刚学主题的时候,我以为 have_posts() 是“判断有没有文章”,the_post() 是“输出文章”。
于是我一直觉得奇怪:为什么循环里明明调了 the_post(),页面却没输出任何东西?正文还得再调一次 the_content()?
后来才明白,这两个函数的分工跟我以为的完全不一样。
把文章列表想成一本书,每一页是一篇文章。have_posts() 和 the_post() 分别干两件事:
have_posts():还有下一页吗?(返回真或假)the_post():翻到下一页(把“当前页”设为下一篇文章)注意:the_post() 不输出任何东西,它只负责“翻页”。翻完之后,你才能调 the_title()、the_content() 这些标签,把这一页的内容读出来。
所以一个标准的循环长这样:
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<h2><?php the_title(); ?></h2>
<?php the_content(); ?>
<?php endwhile; endif; ?>
拆开看:
if ( have_posts() ):先确认这本书不是空的;while ( have_posts() ):只要还有下一页,就继续;the_post():翻到下一页(此时“当前文章”变了);the_title() / the_content():输出当前这一页的内容;endwhile:回去看还有没有下一页。如果你写成这样:
<?php while ( have_posts() ) : ?>
<?php the_title(); ?>
<?php the_post(); ?>
<?php endwhile; ?>
循环能跑,但输出的标题会“错位”——第一次循环时还没翻页,拿到的是上一篇文章的标题;最后一篇的标题会被跳过。因为 the_title() 读的是“当前页”,而“当前页”是 the_post() 决定的。
记住一句话:先翻页(the_post),再读内容(the_title/the_content)。
看 caogenbj 的 index.php,它就是标准写法:
<?php if( have_posts() ) : while( have_posts() ) : the_post(); ?>
<li class="list-group-item">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
<h5 class="text-right">发布时间: <?php the_time('Y-m-d') ?></h5>
</li>
<?php endwhile; ?>
...
<?php endif; ?>
注意 endif 的位置——它在分页代码之后。也就是说,分页也被包在“有文章”的判断里。这个细节后面讲分页时会再说。
有人以为 the_post() 是“把文章数据存进数据库”或者“发布文章”。不是。它只动一个内部指针,告诉 WordPress“现在轮到第几篇了”。
这个指针藏在全局变量 $wp_query 里,下一篇会讲它。
一句话记住:have_posts 是“还有吗”,the_post 是“翻页”,the_title/the_content 是“读这一页”。
先翻页再读,顺序不能反。
下一篇讲一个更底层的问题:the_title() 这些标签,数据到底从哪来。