WordPress 管理員搜索:擴展結果

已發表: 2021-01-20

有時在網站上查找內容可能很困難。 作為 WordPress 管理員,越容易找到您想要的內容就越好。 值得慶幸的是,WordPress 在您將使用的大多數管理屏幕(例如帖子屏幕)上都提供了搜索功能。 儘管此搜索功能很好,但它仍然在許多方面受到限制。

例如,如果您在帖子管理屏幕中搜索帖子,默認情況下,搜索功能將在帖子標題、帖子摘錄和帖子內容中查找搜索查詢文本,然後返回這些結果。 但是,如果您想使用與自定義字段相關的關鍵字進行搜索怎麼辦? 此信息不包含在管理員帖子列表表搜索結果中,這可能會令人沮喪。

在之前的文章中,我們學習瞭如何在我們的帖子類型中添加自定義字段。 讓我們看看如何在搜索結果中包含自定義字段。

在管理屏幕搜索中擴展搜索查詢

在我們關於自定義字段的工作示例中,我們在其中一個帖子中創建了一個名為“source”的自定義字段並插入了一個 URL 值。

如果您進入帖子列表並在搜索欄中使用這些“來源”值之一,您將不會得到任何結果,因為 WordPress 在默認情況下搜索時根本不查看自定義字段。

為了改變這一點,我們需要擴展 WordPress 為搜索功能提供的原始鉤子。 我們必須擴展的鉤子是pre_get_posts ,它包含在wp-includes/class-wp-query.php文件中get_posts函數內的第 1779 行附近。

WordPress 查詢

每次您訪問頁面時,無論是在前視圖還是管理區域,都會執行一系列代碼腳本,以創建與您的請求相對應的WP_Query對象及其屬性。

讓我們創建一些查詢屬性輸出的臨時視圖,以了解在每種情況下WP_Query對像中發生的變化。

為了在執行之前查看查詢,我們將在pre_get_posts操作掛鉤中附加打印。 pre_get_posts過濾器在創建查詢變量對象之後觸發,但在實際查詢運行之前。

在活動主題的functions.php文件中插入這段代碼:

 add_action( 'pre_get_posts', 'print_query' ); function print_query( ) { print_r ( $GLOBALS['wp_query']->query ); echo "<hr>"; print_r ( $GLOBALS['wp_query']->query_vars ); echo "<hr>"; }

現在,如果您訪問 Posts 管理屏幕, queryquery_var的輸出將打印在頂部。

要更輕鬆地查看代碼,您可以將其複制並粘貼到免費的在線 PHP 美化器中。

$GLOBALS['wp_query']->query數組(先出)將如下所示:

 Array ( [order] => [orderby] => [post_type] => post [posts_per_page] => 20 [post_status] => [perm] => )

例如,在帖子管理屏幕中進行搜索時,數組輸出將更改,包括搜索字符串。 例如,如果我們搜索“wordpress.org”,它將如下所示:

 Array ( [m] => 0 [cat] => 0 [s] => wordpress.org [paged] => 1 [order] => [orderby] => [post_type] => post [posts_per_page] => 20 [post_status] => [perm] => )

組裝代碼

記住以上信息我們將插入正確的代碼來實現我們需要的搜索功能。 為此,請返回活動主題的functions.php並刪除您剛才在上一步中插入的代碼。 然後插入下面的代碼:

 add_action( 'pre_get_posts', 'extend_admin_search' ); function extend_admin_search( $query ) { $post_type = 'post'; $custom_fields = array("source",); if( ! is_admin() ) return; if ( $query->query['post_type'] != $post_type ) return; $search_term = $query->query_vars['s']; $query->query_vars['s'] = ''; if ( $search_term != '' ) { $meta_query = array( 'relation' => 'OR' ); foreach( $custom_fields as $custom_field ) { array_push( $meta_query, array( 'key' => $custom_field, 'value' => $search_term, 'compare' => 'LIKE' )); } $query->set( 'meta_query', $meta_query ); }; }

下一步是將$post_type$custom_fields變量更改為適用於您的要求的值。 讓我們看看我們在代碼中做了什麼。

  • $post_type = 'post'; – 在這裡我們定義我們要搜索的帖子類型。
  • $custom_fields = array("source",); – 在這裡我們定義我們想要搜索的自定義字段。

因為我們正在使用pre_get_posts鉤子,所以在我們的代碼中確保我們在正確的頁面上應用我們的自定義搜索擴展是很重要的。 Τo 告訴 WordPress 在特定條件下顯示我們的代碼,我們使用一些條件標籤。

  • if ( ! is_admin() ) return; 條件確保如果我們不在管理區域,我們的任何代碼都不會執行。
  • if ( $query->query['post_type'] != $post_type )檢查我們是否在$post_type變量中定義的帖子類型上工作。 在我們的例子中, post .
  • $search_term = $query->query_vars['s']; 是我們將搜索字符串保存在變量中,然後我們再次將其設置為空$query->query_vars['s'] = ''; 否則它將找不到任何東西。

現在,有了這些更新,如果您刷新上次搜索,您將獲得正確的結果。 在我們的例子中,我們在結果中看到“帖子 1”帖子,其中包括“來源”自定義字段條目:“https://dev. wordpress.org /reference/functions/add_post_meta/'。

改進 wordpress 管理員搜索

在前視圖搜索中擴展搜索查詢

現在我們已經“修復”了我們的管理員搜索,我們可以繼續改進我們的前端搜索功能,以便我們的網站用戶也可以搜索自定義字段。

與以前管理員搜索不會為自定義字段生成任何結果的方式相同,前端搜索也無法返回任何自定義字段的結果。

理想情況下,我們希望用戶能夠搜索這些字段。 在此示例中,我們的一篇文章中有一個自定義的“來源”字段,該字段當前包含 URL“https://dev.wordpress.org/reference/functions/add_post_meta/”。 如果用戶搜索“wordpress.org”,則此帖子應顯示在結果中。 讓我們看看如何做到這一點。

所需的代碼

再次前往您的functions.php 文件並複制您之前粘貼的代碼。 現在,將其直接粘貼到該代碼下方(因此您在functions.php中有此代碼的兩個副本) 現在,將第二批代碼中的函數名稱更改為類似於extend_front_search的名稱。 它應該如下所示:

 add_action( 'pre_get_posts', 'extend_admin_search' ); function extend_admin_search( $query ) { $post_type = 'post'; $custom_fields = array("source",); if( ! is_admin() ) return; if ( $query->query['post_type'] != $post_type ) return; $search_term = $query->query_vars['s']; $query->query_vars['s'] = ''; if ( $search_term != '' ) { $meta_query = array( 'relation' => 'OR' ); foreach( $custom_fields as $custom_field ) { array_push( $meta_query, array( 'key' => $custom_field, 'value' => $search_term, 'compare' => 'LIKE' )); } $query->set( 'meta_query', $meta_query ); }; }

接下來,我們需要刪除if ( $query->query['post_type'] != $post_type ) return; 健康)狀況。

 add_action( 'pre_get_posts', 'extend_front_search' ); function extend_front_search( $query ) { $post_type = 'post'; $custom_fields = array("source",); if( is_admin() ) return; $search_term = $query->query_vars['s']; $query->query_vars['s'] = ''; if ( $search_term != '' ) { $meta_query = array( 'relation' => 'OR' ); foreach( $custom_fields as $custom_field ) { array_push( $meta_query, array( 'key' => $custom_field, 'value' => $search_term, 'compare' => 'LIKE' )); } $query->set( 'meta_query', $meta_query ); }; }

我們只需要維護條件if( is_admin() ) return; 確保代碼僅適用於前端,我們很高興。

另一種策略

擴展 WordPress 搜索以包含自定義字段的另一種方法是更改​​ SQL 查詢。

WP_Query類通過將其分解為wp-includes/class-wp-query.php文件的第 2897 行所描述的部分來幫助您。

 $clauses = (array) apply_filters_ref_array( 'posts_clauses_request', array( compact( $pieces ), &$this ) ); $where = isset( $clauses['where'] ) ? $clauses['where'] : ''; $groupby = isset( $clauses['groupby'] ) ? $clauses['groupby'] : ''; $join = isset( $clauses['join'] ) ? $clauses['join'] : ''; $orderby = isset( $clauses['orderby'] ) ? $clauses['orderby'] : ''; $distinct = isset( $clauses['distinct'] ) ? $clauses['distinct'] : ''; $fields = isset( $clauses['fields'] ) ? $clauses['fields'] : ''; $limits = isset( $clauses['limits'] ) ? $clauses['limits'] : '';

正如我們之前在自定義字段文章中提到的,所有自定義字段數據都存儲在數據庫中的“postmeta”表中,默認情況下該表不包含在 WordPress 搜索中。 所以我們的第一步是使用下面的代碼連接這兩個表

 function join_meta_table( $join ) { global $wpdb; if ( is_search() ) { $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '..post_id '; } return $join; } add_filter('posts_join', 'join_meta_table' );

我們當然使用了posts_join鉤子,因為它過濾了查詢的 JOIN 子句。

接下來,我們將使用posts_where掛鉤來更改查詢的 WHERE 部分以滿足我們的需要。

 function modify_where_clause( $where ) { global $pagenow, $wpdb; if ( is_search() ) { $where = preg_replace( "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/", "(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where ); } return $where; } add_filter( 'posts_where', 'modify_where_clause' );

最後但同樣重要的是,我們需要防止重複。 為此,我們使用過濾查詢的 DISTINCT 子句的posts_distinct掛鉤。

 function prevent_duplicates( $where ) { global $wpdb; if ( is_search() ) { return "DISTINCT"; } return $where; } add_filter( 'posts_distinct', 'prevent_duplicates' );

現在讓我們看看如果我們搜索“wordpress.org”字符串在前端會發生什麼。

前端的wordpress搜索

不出所料,這次的結果是正確的。 WordPress 搜索結果發現“post 1”,因為它包含值為“https://dev”的“源”字段。 wordpress.org /reference/functions/add_post_meta/

WordPress 搜索結果中的自定義帖子類型

您可能想要做的另一件事是使自定義帖子類型可搜索(如果您不確定如何創建自定義帖子類型,請確保在此處查看我們的文章)。

假設我們創建了一個名為“books”的自定義帖子類型,我們希望這個帖子類型出現在搜索結果中。 這次我們不必重新創建 SQL 查詢,只需在pre_get_posts鉤子中重新定義帖子類型,如下所示。 代碼必須再次放置在functions.php文件中。

 function tg_include_custom_post_types_in_search_results( $query ) { if ( $query->is_main_query() && $query->is_search() && ! is_admin() ) { $query->set( 'post_type', array( 'post', 'books' ) ); } } add_action( 'pre_get_posts', 'tg_include_custom_post_types_in_search_results' );

我們在這裡所做的是將要包含在搜索結果中的所需帖子類型作為參數添加到post_type掛鉤。

如果您想排除一種類型,只需將其從數組中刪除即可。

結論

改進 WordPress 網站上的搜索確實很有幫助,並且可以節省大量時間。 對於您的最終用戶來說,他們可以搜索自定義帖子類型和自定義字段也很重要。 希望上面的說明能讓您深入了解如何在您自己的網站上實現這一目標。