我对“循环”有疑问。

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>


代码取自Loop WordPress Codex页面。
好像有if循环,就可以正常工作。

如果没有while语句,在什么情况下会出现问题?

编辑

我接受了@Chip的回答。但老实说我只需要最后一部分。

我现在知道我想从我的问题中知道什么。想要放置仅应写入一次的页眉或页脚。如果您不使用“包装器”,则不需要if语句。


评论

我在阅读the_content之前投票赞成,the_title是决定性的!

优秀(最终)编辑。大多数人彼此直接使用if和while,而从未使用过else。可能是因为复制粘贴。

#1 楼

WordPress模板加载器在许多情况下都将包括适当的上下文模板文件,即使该上下文的查询未返回任何帖子。例如:


主博客文章索引
类别存档索引(类别存在,但没有帖子)
标签存档索引(标签存在,但没有标签)帖子)
作者存档索引(作者存在,但没有帖子)将输出,因为查询不返回任何帖子。

概念验证示例:



类别存在,但没有帖子(

类别不存在(包括404模板)

因此,在这些情况下,模板文件包含条件if ( have_posts() )很有用。

在其他情况下,如果查询不返回任何帖子,则将永远不会加载模板文件。例如:


单个博客文章
在这种情况下,可能不需要if ( have_posts() )

编辑


我知道该查询由the_post()调用,对吗?而且,如果while(have_posts())存在,那么如果没有发布,则永远不会进行查询。以wp_loaded开头(为清楚起见,省略了一些内容):


wp_loaded
parse_request
send_headers
parse_query
pre_get_posts
wp
template_redirect
get_header
wp_head
the_post
wp_footer

那么,怎么回事,按什么顺序?
查询被调用:

parse_query
pre_get_posts
wp


已选择模板:

template_redirect


模板已加载/输出。模板会触发以下操作:

get_header
wp_head
the_post
dynamic_sidebar
get_footer
wp_footer




因此,由the_post触发的the_post()发生在解析查询,获取帖子和模板之后已加载。


非常感谢您提供了许多我不知道的信息,但这不是我要的。


哦,但我相信这正是您的要求。

真正的问题是:有效的查询返回是什么?对于类别存档索引之类的上下文,查询有效,并且即使存在查询的类别ID(即使没有分配给该类别的帖子),也加载了类别模板。为什么?因为要解析的查询是(IIRC)&cat={ID}-即使没有分配给该类别的帖子,这也是一个有效的查询,因此在解析时不会导致404。 ,您将获得一个有效的查询,并加载了一个模板文件,但没有任何帖子。因此,if ( have_posts() )实际上是相关的。同样,这是一个示例:存在类别,但未分配任何帖子。类别模板文件已加载,其中if ( have_posts() )返回false

编辑2


如果我正确地理解是否没有if(have_posts( ))在类别模板中,并且类别没有帖子,那么即使它应该是没有帖子的return category-sample.php,它也会返回404.php。是吗?


不。请记住:已在&p={ID}上选择了模板。因此,如果查询有效,那么将加载适当的模板文件。如果查询无效,则会加载404模板。

因此,一旦加载了模板-例如类别模板-输出循环后,模板不会更改。

再次查看操作顺序:


template_redirect
parse_query
pre_get_posts

wp-选择模板并在此处加载。这是不可退回的模板点。此后模板无法更改。
...

template_redirect-在循环调用中,此处已设置postdata。这在模板内部被调用,并且模板不会根据查询对象中的可用数据而更改

最终编辑


检查帖子的存在情况,为什么我应该两次运行相同的测试。从一开始我就是一直问这个问题。 WordPress循环。您是在询问将任意PHP the_post循环包装在检查相同条件的while条件中。 br /> if条件是二进制评估:它是iftrue,并且该条件内部发生的事情只执行一次。 ,基于某种计数器;并多次执行该条件内发生的事情-每次计数器迭代一次。

因此,假设您要输出无序的事物列表(如果填充了事物列表) 。如果使用false循环并省略while包装器,则标记将如下所示: br />
<ul>
<?php while ( list_of_things() ) : ?>
    <li><?php the_list_item(); ?></li>
<?php endwhile; ?>
</ul>


留下了不必要的(和无效的)标记。

但是如果添加while条件包装器,则可以执行以下操作:

<ul>
</ul>


如果if为空,则根本不会输出任何标记。

那只是一个例子。该list_of_things()条件包装器有很多用途,而if条件包装器的用途与list_of_things()循环的用途完全不同。

评论


很长一段时间以来,在我单一的帖子/页面模板中,我只使用the_post();。因为那一刻也是不必要的。 +1为信息的完整性。

– gmazzap♦
2013年10月9日17:00

@GM可能删除if(have_posts())语句很有意义(这就是我要找出的内容),但不要只在单个页面中使用the_post()!

– Sunyatasattva
13-10-12在20:53

@ChipBennett全部考虑,您是否认为在单个* .php和page-*。php模板文件的上下文中的完整循环之前删除if(have_post())条件是否安全?

– Sunyatasattva
13-10-12在20:55

在这种情况下,“安全”确实没有明确的含义。

–芯片Bennett
13-10-12在21:05

#2 楼

实际上,要改善Chip的答案是不可能的,而只是切合实际:

如果您想在没有帖子的情况下显示一些其他内容,请使用if部分。例如,在日期或类别存档页面上,这特别有用。如果有人导航到没有帖子的页面,那么很高兴收到这样一条消息,而不是什么也没显示,因为循环永远不会执行。

if ( have_posts() ):
  // Yep, we have posts, so let's loop through them.
  while ( have_posts() ) : the_post();
  // do your loop
  endwhile;
else :
  // No, we don't have any posts, so maybe we display a nice message
  echo "<p class='no-posts'>" . __( "Sorry, there are no posts at this time." ) . "</p>";
endif;


评论


这就是所有需要知道的。

– Herbert Van-Vliet
18年5月18日在21:08

#3 楼

到目前为止,答案中可能还没有包括一些注意事项。不建议省略if语句。

if语句通常用于:没有为其分配任何文章。
确定是否应在文章前后输出周围的html(如ul)。

如果添加了新的钩子怎么办? br />不使用if语句的另一个可能的问题是,如果wordpress团队决定添加一个新的钩子,该钩子会在第一个no posts found调用时触发,那么它将在错误的时间触发。如果这导致了意外的行为,则可能是您未能正确遵循规范而引起的错误。希望看到整个wordpress循环。因此,让他们搜索不存在的if语句可能不是一个好主意。

#4 楼

我认为这是控制结构理论的基本问题。即使条件(have_posts())第一次评估为false,while循环中的封闭块也不会执行一次。

因此,WordPress循环中if ( have_posts() )的目的是在对while条件求值之前仅执行一次have_posts()函数。如果have_posts()没有副作用,则if ( have_posts() )完全没有意义。如果have_posts()确实有副作用,则可以简化如下:

<?php have_posts(); ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>


评论


这种简化是无效的PHP,您有一个else语句,该语句没有附加的if语句。充其量很难读

– Tom J Nowell♦
14-10-23在23:27

如果在那儿是因为后面的其他。没有其他原因。如果没有帖子,那么显示一个很好的“ no posts”消息比什么都不显示更好。

–奥托
14-10-24在0:13