WordPress模板加载器在许多情况下都将包括适当的上下文模板文件,即使该上下文的查询未返回任何帖子。例如:
- 主要博客文章索引
- 类别存档索引(类别存在,但没有帖子)
- 标签存档索引(标签存在,但没有帖子)
- 作者存档索引(作者存在,但没有帖子)
- 搜索结果索引
因此,在这些情况下,将加载适当的模板文件,但不会输出任何帖子,因为查询不会返回任何帖子。
概念验证示例:
因此,在这些情况下,模板文件包含if ( have_posts() )
条件是很有用的。
在其他情况下,如果查询不返回任何帖子,则将永远不会加载模板文件。例如:
在这些情况下,if ( have_posts() )
可能是不必要的。
编辑
我了解查询是由the_post()调用的,对吧?并且,如果while(have_posts())存在,那么如果没有发布,则永远不会进行查询。
要了解发生了什么,您必须查看WordPress操作的顺序。开始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
- 选择模板:
- 模板已加载/输出。模板会触发以下操作:
get_header
wp_head
the_post
dynamic_sidebar
get_footer
wp_footer
因此,the_post
由触发的the_post()
会在解析查询,提取帖子和加载模板后很长时间发生。
非常感谢您提供了许多我不知道的信息,但这不是我要的。
哦,但是我相信这正是您的要求。
真正的问题是:有效的查询返回是什么?对于诸如类别归档索引之类的上下文,即使存在查询的类别ID,即使没有分配给该类别的帖子,查询也是有效的,并且会加载类别模板。
为什么?因为要解析的查询是(IIRC)&cat={ID}
- 即使没有分配给该类别的帖子,这也是一个有效的查询,因此在解析时不会导致404。
在这种情况下,您将获得一个有效的查询,并加载了一个模板文件,但是没有posts。因此,if ( have_posts() )
,,其实相关的。同样,这是一个示例:存在类别,但未分配任何帖子。类别模板文件已加载,并if ( have_posts() )
返回false
。
对于包含帖子变量(&p={ID}
)的查询(例如单个博客帖子和静态页面),这将不成立,因为该帖子实际上并不存在,并且在解析后,该查询将不会返回有效的对象。
编辑2
如果我正确理解类别模板中是否没有if(have_posts())并且类别没有帖子,那么即使它应该返回没有帖子的category-sample.php,它也会返回404.php。那正确吗?
否。请记住:已在选择模板template_redirect
。因此,如果查询有效,那么将加载适当的模板文件。如果查询无效,则将加载404模板。
因此,一旦加载模板(例如类别模板),则在输出循环后,模板就不会更改。
再看一下操作顺序:
parse_query
pre_get_posts
wp
template_redirect
- 选择模板并在此处加载。这是无法回报的模板。此后,模板将无法更改。
- ...
the_post
- 在此设置postdata,作为循环调用的一部分。这在模板内部被调用,并且模板不会根据查询对象中的可用数据而更改
最终编辑
我声称在检查帖子的存在时,为什么我应该运行两次相同的测试。从一开始我就是一直在问这个问题。
这样,我终于明白了:一直以来,您的问题与WordPress或WordPress Loop无关。您在问有关while
在if
检查相同条件的条件中包装任意PHP 循环的问题。
这个问题不在WPSE的范围内,但我将简要说明:
一个if
条件是一个二元的评价:它要么true
或false
,会发生什么,里面是有条件的,执行一次。
一个while
条件是一个循环:这对一些离散时期仍是如此,基于某种计数器; 并且该条件内发生的情况会执行多次 - 每次计数器迭代一次。
因此,假设您要输出无序的事物列表(如果已填充事物列表)。如果使用while
循环并省略if
包装器,则标记将如下所示:
<ul>
<?php while ( list_of_things() ) : ?>
<li><?php the_list_item(); ?></li>
<?php endwhile; ?>
</ul>
如果list_of_things()
为空,则呈现的输出为:
<ul>
</ul>
留下不必要(和无效)的标记。
但是,如果添加if
条件包装器,则可以执行以下操作:
<?php if ( list_of_things() ) : ?>
<ul>
<?php while ( list_of_things() ) : ?>
<li><?php the_list_item(); ?></li>
<?php endwhile; ?>
</ul>
<?php endif; ?>
如果list_of_things()
为空,则不会输出任何标记。
那只是一个例子。该if
条件包装器有很多用途,条件包装if
器的用途与while
循环的用途完全不同。