問題描述

Codex 和 blogosphere 周圍的教程中,有一半使用 query_posts(),一半使用 WP_Query 。這是怎麼回事?

最佳解決方案

  •  query_posts()透過用查詢的新例項替換來修改頁面的主查詢過於簡單和有問題的方法。它是低效的 (re-runs SQL 查詢),並將在一些情況下 (特別是經常處理帖子分頁時) 會徹底失敗。任何現代的 WP 程式碼都應該使用更可靠的方法,例如使用 pre_get_posts 鉤子。 長話短說不要使用 query_posts();
  •  get_posts()在使用上非常相似,並接受相同的引數 (具有一些細微差別,如不同的預設值),但是返回陣列,不會修改全域性變數,並且可以安全地在任何位置使用;
  •  WP_Query 類功能在幕後,但您也可以建立和使用自己的物件。位更復雜,限制較少,也可以隨時隨地使用。

次佳解決方案

 query_posts – 你永遠不應該使用 query_posts 。除了 @Rarst 所說的,query_posts 的真正大問題是它打破了主查詢物件 (儲存在 $wp_query 中) 。大量的外掛和自定義程式碼依賴於主查詢物件,所以打破主查詢物件意味著您正在破壞外掛和自定義程式碼的功能。只有一個這樣的功能是所有重要的分頁功能,所以如果你打破主要查詢,你打破分頁。

要證明 query_posts 在任何模板上有多糟糕,請執行以下操作並比較結果

var_dump( $wp_query );
query_posts( '&posts_per_page=-1' );
var_dump( $wp_query );

 get_postsWP_Query 是構建輔助查詢 (如靜態首頁上的相關帖子,滑塊,精選內容和內容) 的正確方法。應該注意的是,您不應該使用主頁,單頁或任何型別的歸檔頁面中的主要查詢中的任何一個,因為它會破壞頁面功能。如果需要修改主查詢,請使用 pre_get_posts 來做,而不是自定義查詢。 (更新:對於靜態前頁和真實頁面,請參閱 Using pre_get_posts on true pages and static front pages *)

實質上,WP_Query 主要用於查詢,也由 get_posts 使用,但 get_posts()雖然使用 WP_Query,但有一些差異

  •  get_postsWP_Query 快。利潤率取決於網站總數量。其原因是 get_posts 預設透過'no_found_rows' => true WP_Query 跳過/合法分頁。使用'no_found_rows' => trueWP_Query 獲取查詢的帖子數量,然後快取,預設情況下,它進一步搜尋與查詢匹配的所有帖子,以便計算分頁。因此,get_posts()只能用於非分頁查詢。分頁 get_posts 真是一大難題。 WP_Query 應用於所有分頁查詢
  •  get_posts()不受 posts_*過濾器的影響,WP_Query 會受到這些過濾器的影響。原因是 get_posts 預設透過'suppress_filters' => trueWP_Query
  •  get_posts 具有幾個額外的引數,如 includeexcludenumberpostscategory 。在傳遞給 WP_Query 之前,將這些引數更改為 WP_Query 的有效引數。 include 變為 post__inexclude 轉化為 post__not_incategory 轉化為 catnumberposts 轉化為 posts_per_page 。只需一個註釋,所有可以傳遞給 WP_Query 的引數都可以使用 get_posts,您可以忽略而不使用 get_posts 的預設引數
  •  get_posts 只返回 WP_Query$posts 屬性,而 WP_Query 返回完整的物件。當涉及到可以在迴圈中使用的條件,分頁和其他有用的資訊時,此物件非常有用。
  •  get_posts 不使用迴圈,而是使用 foreach 迴圈來顯示帖子。此外,預設情況下,沒有模板標籤可用。 setup_postdata( $post )必須用於使模板標籤可用。 WP_Query 預設使用迴圈和模板標記
  •  get_posts 透過'ignore_sticky_posts' => 1WP_Query,預設情況下 get_posts 忽略粘帖

基於上述,是否使用 get_postsWP_Query 取決於您,您從查詢中實際需要什麼。以上應引導您選擇

第三種解決方案

基本的區別是 query_posts()真的只是為了修改當前的 Loop 。一旦完成,就需要重新設定迴圈並以快捷的方式傳送。這個方法也更容易理解,只是因為你的”query” 基本上是一個你傳遞給函式的 URL 字串,像這樣:

query_posts('meta_key=color&meta_value=blue');

另一方面,WP_Query 更是一種通用工具,更像直接編寫 MySQL 查詢,而不是 query_posts()。你也可以在任何地方使用它 (不只是在迴圈中),它不會干擾任何當前執行的帖子查詢。

我更傾向於使用 WP_Query,因為它會發生。真的,這將會歸結於你的具體情況。

第四種方案

沒有必要使用 query_posts()。它所做的就是例項化一個新的 WP_Query 物件,並將該新物件重新分配給 global wp_query

作為參考,以下是實際的 query_posts()功能。

 function query_posts($query) {
        $GLOBALS['wp_query'] = new WP_Query();
        return $GLOBALS['wp_query']->query($query);
    }

如果要建立深度自定義查詢指令碼,則例項化自己的 WP_Query 物件。或者使用 get_posts(),如果你需要做的就是這裡和那裡的一些光線操縱。

無論哪種情況,我強烈建議您自己動手,並去 wp_includes/query.php,並閱讀 WP_Query 課程。

第五種方案

使用 query_posts()後,請確保使用 wp_reset_query(),因為它也會影響其他查詢結果。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。