wordpress中的2個查詢方法query_posts()
和WP_Query
到底有什麽區別和聯係?分別應該在什麽情形下使用?
各種博客教程中2種方法都有涉及,但是沒有明確區分,讓人比較困惑,這個問題怎麽破?
主流的理解思路
query_posts()
過於簡單並且存在問題,通過用查詢的新實例替換頁麵的主查詢來修改主查詢。相對來說這個函數效率較低下(re-runs SQL查詢),並在某些情況下可能會徹底失敗(特別是在處理帖子分頁時)。任何當前的WP代碼都應該使用更可靠的方法,例如使用pre_get_posts
掛鉤。 長話短說盡量不要使用 query_posts();get_posts()
在用法上非常相似,並且接受相同的參數(具有一些細微差別,如不同的默認值),但返回帖子數組,不修改全局變量並且可以安全地在任何地方使用;WP_Query
類既支持後台默認流程,也可以自己創建和使用它的對象。用法更複雜,限製更少,也可以安全地在任何地方使用。
次佳解決思路
query_posts
– 您永遠不應該使用query_posts
。除了上文所說的,query_posts
真正的大問題是,它破壞了主查詢對象(存儲在$wp_query
中)。很多插件和自定義代碼都依賴於主查詢對象,因此打破主查詢對象意味著您打破了插件和自定義代碼的功能。主函數影響分頁功能,所以如果你打破了主要查詢,就會破壞分頁。
要證明query_posts
有多糟糕,請在任何模板上執行以下操作並比較結果
var_dump( $wp_query );
query_posts( '&posts_per_page=-1' );
var_dump( $wp_query );
get_posts
和WP_Query
是構建輔助查詢(如靜態首頁上的相關文章,滑塊,精選內容)的正確方法。應該注意的是,不應該在主頁,單頁或任何類型的歸檔頁麵上使用兩者中的任何一個,因為它會破壞頁麵功能。如果需要修改主查詢,請使用pre_get_posts
來完成,而不是自定義查詢。 (更新:對於靜態首頁和真實頁麵,請參閱Using pre_get_posts on true pages and static front pages *)
實質上,WP_Query
由主查詢使用,也由get_posts
使用,但雖然get_posts()
使用WP_Query
,但有一些差異
get_posts
比WP_Query
更快。區別取決於網站的總帖子數量。原因是,get_posts
默認將'no_found_rows' => true
傳遞給WP_Query
,WP_Query
會跳過/合法地中斷分頁。使用'no_found_rows' => true
,WP_Query
獲取查詢的帖子數量,然後保留,默認情況下,它會進一步搜索與查詢匹配的所有帖子以計算分頁。因此,get_posts()
隻能用於非分頁查詢。分頁get_posts
真的是一個大混亂。WP_Query
應該用於所有分頁查詢get_posts()
不受被WP_Query
影響的posts_*
過濾器的影響。原因是get_posts
默認將'suppress_filters' => true
傳遞給WP_Query
get_posts
有幾個額外的參數,如include
,exclude
,numberposts
和category
。在傳遞給WP_Query
之前,這些參數會變為WP_Query
的有效參數。include
變為post__in
,exclude
變為post__not_in
,category
變為cat
,numberposts
變為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' => 1
傳遞給WP_Query
,因此get_posts
默認忽略粘性帖子
基於上述情況,是否使用get_posts
或WP_Query
取決於您,您在查詢中實際需要什麽。以上應引導您選擇
第三種解決思路
基本區別在於query_posts()
實際上隻是用於修改當前循環。一旦你完成了,有必要重新設置循環並將其快速發送。這個方法也比較容易理解,因為你的”query”基本上是一個URL字符串,你傳遞給函數,如下所示:
query_posts('meta_key=color&meta_value=blue');
另一方麵,WP_Query
更像是一種通用工具,更像是直接編寫MySQL查詢,而不是query_posts()
。你也可以在任何地方使用它(不隻是在循環中),它不會幹擾任何當前正在運行的後期查詢。
第四種思路
根本不需要使用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()
,如果你需要做的隻是一些輕微的操縱。
參考資料