WordPress 自定義查詢 – 使用 WP_Query 類

已發表: 2021-02-06

WordPress 提供了廣泛的即用型功能,在大多數情況下可以從數據庫中檢索必要的信息。 但是在開發 WordPress 網站時,有很多情況下過濾器或操作不足以達到預期的結果。 在這些情況下。 WordPress 以WP_Query類的形式提供了一種解決方法。

讓我們看看如何使用WP_Query類!

自定義查詢案例

注意:本文假設您對 PHP 和 MySQL/MariaDB 有一定的了解,並且熟悉使用 WordPress。

無論您訪問什麼頁面,WordPress 都會運行所謂的“主查詢”來顯示內容。 因此,當您訪問例如類別視圖之類的頁面時,會在後台創建一個WP_Query對象,並從數據庫中檢索所有必要的數據以顯示該頁面。

WP_Query的基本作用是讓您能夠從網站的數據庫中檢索內容,而無需使用 SQL 查詢。

為此,我們需要做的就是定義與我們的需求相對應的參數,然後將創建一個新的WP_Query對象並將其轉換為 SQL 查詢。

使用 WP_Query 的示例

如果我們想在另一個類別模板​​中顯示來自特定類別的帖子,則需要創建一個新的查詢對象。

出於本示例的目的,我們激活了二十二十個主題,並在名為“類別 1”的類別下創建了 2 個帖子,並在名為“服務”的類別下創建了 2 個帖子。

此外,我們為“類別 1”帖子創建了一個自定義類別視圖模板。 這個類別的 slug 是 'category-1' 因此主題文件夾下的文件應該是category-CATEGORYSLUG.php ,在我們的例子中是category-category-1.php

請將以下內容粘貼到category-category-1.php文件中。

 <?php /*** Custom Category 1 Template */ get_header(); ?> <main role="main"> <section class="site-content"> <div role="main"> <?php if ( have_posts() ) : ?> <header class="archive-header"> <h3 class="archive-title">Category: <?php single_cat_title( '', true ); ?></h3> </header> <?php while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; endif; ?> </div> </section> </main> <?php get_sidebar(); ?> <?php get_footer(); ?>

在循環之前,我們使用have_posts方法來確定循環中是否有更多可用的帖子。

the_post()是循環迭代帖子並告訴 WordPress 移動到帖子數組的下一個帖子所必需的。

此時,我們的類別 ( https://mycompanyname.com/category/category-1/ ) 的前端視圖將如下所示:

我知道通過使用這段代碼,我們忽略了包含很多帖子信息,但是為了這個示例,最好保持簡單並且只顯示帖子標題。

要查看 WordPress 為此視圖創建的查詢對象屬性,我們只需在代碼中的endif; 陳述。

 var_dump ( $wp_query->query_vars );

現在,如果您刷新頁面,您將在帖子列表下看到此信息:

 array(63) { ["category_name"]=> string(10) "category-1" ["error"]=> string(0) "" ["m"]=> string(0) "" ["p"]=> int(0) ["post_parent"]=> string(0) "" ["subpost"]=> string(0) "" ["subpost_id"]=> string(0) "" ["attachment"]=> string(0) "" ["attachment_id"]=> int(0) ["name"]=> string(0) "" ["pagename"]=> string(0) "" ["page_id"]=> int(0) ["second"]=> string(0) "" ["minute"]=> string(0) "" ["hour"]=> string(0) "" ["day"]=> int(0) ["monthnum"]=> int(0) ["year"]=> int(0) ["w"]=> int(0) ["tag"]=> string(0) "" ["cat"]=> int(16) ["tag_id"]=> string(0) "" ["author"]=> string(0) "" ["author_name"]=> string(0) "" ["feed"]=> string(0) "" ["tb"]=> string(0) "" ["paged"]=> int(0) ["meta_key"]=> string(0) "" ["meta_value"]=> string(0) "" ["preview"]=> string(0) "" ["s"]=> string(0) "" ["sentence"]=> string(0) "" ["title"]=> string(0) "" ["fields"]=> string(0) "" ["menu_order"]=> string(0) "" ["embed"]=> string(0) "" ["category__in"]=> array(0) { } ["category__not_in"]=> array(0) { } ["category__and"]=> array(0) { } ["post__in"]=> array(0) { } ["post__not_in"]=> array(0) { } ["post_name__in"]=> array(0) { } ["tag__in"]=> array(0) { } ["tag__not_in"]=> array(0) { } ["tag__and"]=> array(0) { } ["tag_slug__in"]=> array(0) { } ["tag_slug__and"]=> array(0) { } ["post_parent__in"]=> array(0) { } ["post_parent__not_in"]=> array(0) { } ["author__in"]=> array(0) { } ["author__not_in"]=> array(0) { } ["ignore_sticky_posts"]=> bool(false) ["suppress_filters"]=> bool(false) ["cache_results"]=> bool(true) ["update_post_term_cache"]=> bool(true) ["lazy_load_term_meta"]=> bool(true) ["update_post_meta_cache"]=> bool(true) ["post_type"]=> string(0) "" ["posts_per_page"]=> int(10) ["nopaging"]=> bool(false) ["comments_per_page"]=> string(2) "50" ["no_found_rows"]=> bool(false) ["order"]=> string(4) "DESC" }

假設我們要在上面描述的帖子下顯示屬於“服務”類別的帖子列表。 由於頁面已經為當前類別創建了一個查詢對象,我們必須通過操作現有的主要查詢參數來解決這個問題。

讓我們看一下 WordPress 允許我們實現這一目標的方式。

query_posts 函數

query_posts()函數是一種更改 WordPress 用於顯示帖子的主要查詢的方法。 它通過將主查詢放在一側並用新查詢替換它來做到這一點。 您可以在引入它的wp-includes/query.php文件中親自看到這一點。

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

我們將嘗試通過在endwhile; 當前標準循環。

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile;

你去吧:

然而,這種方法有一個缺點。 如果我們嘗試打印查詢對像中包含的類別,我們會注意到它已更改。

嘗試插入var_dump ( $wp_query->query_vars["category_name"] ); 服務查詢後刷新頁面。 你應該看到這個結果:

 string(8) "services"

發生這種情況是因為查詢已更改但從未恢復。 這種方法可能會導致我們查詢後的內容出現很多問題。

為了避免這些衝突並在調用query_posts後進行清理,請調用wp_reset_query() ,原始主查詢將被恢復。 所以你的代碼應該是這樣的:

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; wp_reset_query(); var_dump ( $wp_query->query_vars["category_name"] );

刷新頁面後,您現在會看到初始頁麵類別又回到了查詢中。

 string(10) "category-1"

最後,我們應該提到應該避免query_posts ,因為它會增加查詢的開銷,因為它實際上會導致主查詢再次運行。

get_posts() 函數

使用get_posts()函數檢索與給定條件匹配的帖子數組可以實現相同的結果。

替換如下所示的服務循環...

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; wp_reset_query(); var_dump ( $wp_query->query_vars["category_name"] );

……有了這個:

 $my_query = get_posts( array ( 'category' => 17 ) ); foreach($my_query as $post) : setup_postdata($post); the_title( '<h4 class="example"></h4>' ); endforeach; var_dump ( $wp_query->query_vars["category_name"] );

正如您所看到的,這一次我們必須使用類別 ID 而不是類別名稱,根據 WordPress 定義的get_posts()參數。

這裡要注意的另一件重要的事情是,即使我們沒有重置查詢,查詢類別的var_dump輸出仍然完好無損,沒有更改為“服務”。 這是因為get_posts()本身不會改變主查詢。 我們只是使用了一個新變量“ $my_query ”來創建查詢對象的一個新實例,而不用替換它。

get_posts()函數使用與query_posts()相同的參數,建議在您想在模板中的任何位置添加靜態自定義循環時使用,因為它安全且易於使用。

創建一個新的 WP_Query 對象

$wp_queryWP_Query類的一個對象,用於檢索當前頁面所需的數據庫內容。 覆蓋這個類是我們自定義結果和顯示不同內容的方式。

這是我們將使用的一段代碼:

 $services_query = new WP_Query( 'category_name=services' ); if ( $services_query->have_posts() ) { while ( $services_query->have_posts() ) : $services_query->the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; } wp_reset_postdata(); var_dump ( $wp_query->query_vars["category_name"] );

我們使用 'category_name' 參數來定義我們希望其帖子顯示的類別的 slug。

我們保存了新對象new WP_Query( 'category_name=services' );$services_query變量中。

然後我們使用一個while循環來顯示內容,然後我們用wp_reset_postdata();重置循環。 為了恢復到主查詢的原始數據。

如果您想試驗 WP_Query WordPress 類的其他參數,您可以在其 WordPress Codex 頁面上找到完整列表。