問題描述
我有一個關於”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(#替換為 @) 。