問題描述

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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。