問題描述
我有一個關於”the loop” 的問題。
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>
代碼取自 The Loop WordPress Codex page 。
為什麼要把 if 放在一起?好像是有 while 循環,工作正常。
在沒有 if 語句的情況下會發生什麼情況?
Edit
我接受了 @ Chip 的回答。但老實説,我只需要最後一部分。
我現在知道我想知道的問題。
ifstatement is only when necessary, if you want to put a header or footer that should be write only once. if you don’t use the “wrapper”, thenifstatement is not necessary.
最佳解決方案
WordPress 模板加載程序將在許多情況下包含適當的上下文模板文件,即使該上下文的查詢不返回任何帖子。例如:
-
主要博客文章索引
-
類別歸檔索引 (類別存在,但沒有帖子)
-
標籤存檔索引 (標籤存在,但沒有帖子)
-
作者存檔索引 (作者存在,但沒有帖子)
-
搜索結果索引
因此,在這些情況下,將加載適當的模板文件,但不會輸出任何帖子,因為查詢不返回帖子。
Proof-of-concept 示例:
-
Category does not exist(包括 404 模板)
因此,在這些上下文中,模板文件包含 if ( have_posts() )條件有用。
在其他上下文中,如果查詢不返回任何帖子,模板文件將永遠不會被加載。例如:
-
單個博文
-
靜態頁面
在這些情況下,if ( have_posts() )可能是不必要的。
Edit
I understand the query is invoked by the_post(), right? And if while(have_posts()) exist, the query is never occurs if there is no post.
要了解發生了什麼,you have to look at the order of WordPress actions 。從 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 會在查詢被解析後發生很長時間,並且將模板加載。
I’m very grateful that you give a lot of information that I didn’t know, but this is not what I asked.
哦,但我相信這正是你所問的。
真正的問題是:什麼是有效的查詢返回?對於諸如類別歸檔索引的上下文,查詢是有效的,並且如果查詢的類別 ID 存在,則加載類別模板,即使沒有分配給該類別的帖子。
為什麼?因為正在解析的查詢是 (IIRC)&cat={ID} – 即使沒有分配給該類別的帖子也是一個有效的查詢,因此在解析時不會導致 404 。
在這種情況下,您會收到一個有效的查詢,並加載了一個模板文件,但沒有發佈任何帖子。因此,if ( have_posts() ),其實是相關的。再次,這裏有一個例子:category 存在,但沒有分配任何帖子。加載類別模板文件,if ( have_posts() )返回 false 。
對於包含一個 post 變量 (&p={ID}) 的查詢 (例如單個博客文章和靜態頁面),這並不適用,因為該帖子實際上不存在,並且在解析時,該查詢將不會返回一個有效的對象。
編輯 2
If I rightly understand if there is no if(have_posts()) in a category template and the category have no post, then it return 404.php, even though it should be return category-sample.php without post. Is that right?
不記得:模板是在 template_redirect 中選擇的。所以如果查詢是否有效,那麼加載相應的模板文件。如果查詢無效,則加載 404 模板。
所以,一旦模板被加載 – 例如類別模板 – 一旦循環輸出,模板不會更改。
再看一下行動的順序:
-
parse_query -
pre_get_posts -
wp -
template_redirect– 在這裏選擇並加載模板。這是不退貨的模板點。此後,模板無法更改。 -
…
-
the_post– postdata 設置在這裏,作為循環調用的一部分。這在模板中被調用,並且模板不會根據查詢對象中的可用數據進行更改
最終編輯
And I’am claiming that while checks existence of posts, why should I run the same test twice. That is my question from first point I’ve been asking only about that.
而且,我終於明白了:一直以來,你的問題與 WordPress 或 WordPress Loop 無關。您正在詢問將任意 PHP while 循環包含在 if 條件中,以檢查相同的條件。
這個問題超出了 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 循環完全不同。
次佳解決方案
改進芯片的答案真的是不可能的,只是為了減少追逐:
如果您想在沒有帖子時顯示不同的東西,請使用 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;
參考文獻
注:本文內容整合自 google/baidu/bing 翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:gxnotes#qq.com(#替換為 @) 。