問題描述

我想將搜索限制在英語+數字上使用的字符。原因是查看最慢的查詢 mysql 日誌我發現大多數來自阿拉伯,俄羅斯和漢字的搜索,所以我想跳過它們並顯示一個錯誤信息。

最佳解決方案

此解決方案通過應用正則表達式來過濾搜索字符串,該正則表達式僅匹配 Common 和 Latin Unicode 腳本中的字符。


匹配拉丁字符與正則表達式

我只是 had my mind blown over at Stack Overflow 。事實證明,正則表達式具有匹配整個 Unicode 類別的 a mechanism,包括用於指定整個 Unicode “scripts” 的值,每個對應於不同寫入系統中使用的字符組。

這是通過使用 p meta-character,後跟大括號中的 Unicode 類別標識符完成的,因此 [p{Common}p{Latin}]Latin or Common scripts 中的單個字符匹配 – 其中包括標點符號,數字和雜項符號。

作為 @Paul ‘Sparrow Hawk’ Biron points outu pattern modifier flag 應設置在正則表達式的末尾,以便 PHP 的 PCRE 功能將主題字符串視為 UTF-8 Unicode 編碼。

所有在一起的模式

/^[p{Latin}p{Common}]+$/u

將匹配由拉丁文和通用 Unicode 腳本中的一個或多個字符組成的整個字符串。


過濾搜索字符串

攔截搜索字符串的好地方是在 WordPress 執行查詢之前立即觸發的 pre_get_posts 操作。更加小心,這也可以使用 request 濾波器完成。

function wpse261038_validate_search_characters( $query ) {
  // Leave admin, non-main query, and non-search queries alone
  if( is_admin() || !$query->is_main_query() || !$query->is_seach() )
    return;

  // Check if the search string contains only Latin/Common Unicode characters
  $match_result = preg_match( '/^[p{Latin}p{Common}]+$/u', $query->get( 's' ) );

  // If the search string only contains Latin/Common characters, let it continue
  if( 1 === $match_result )
    return;

  // If execution reaches this point, the search string contains non-Latin characters
  //TODO: Handle non-Latin search strings
  //TODO: Set up logic to display error message
}

add_action( 'pre_get_posts', 'wpse261038_validate_search_characters' );

響應不允許的搜索

一旦確定一個搜索字符串包含 non-Latin 字符,您可以使用 WP_Query::set()來修改查詢,通過更改它的名稱為 query vars – 從而影響 WordPress 後續編寫和執行的 SQL 查詢。

最相關的查詢變量大概如下:

  • s 是與搜索字符串對應的查詢變量。將其設置為 null 或空字符串 ('') 將導致 WordPress 不再將查詢視為搜索 – 通常會導致存檔模板顯示站點的所有帖子或 front-page,具體取決於其他的值查詢變量。然而,將其設置為單個空格 (' ') 將導致 WordPress 將其識別為搜索,從而嘗試顯示 search.php 模板。

  • page_id 可用於將用户引導到您選擇的特定頁面。

  • post__in 可以將查詢限制為特定的帖子選擇。通過將其設置為具有不可能的帖子 ID 的數組,it can serve as a measure to ensure that the query returns absolutely nothing

考慮到上述情況,您可以執行以下操作,以便通過加載 search.php 模板來響應不正確的搜索結果:

function wpse261038_validate_search_characters( $query ) {
  // Leave admin, non-main query, and non-search queries alone
  if( is_admin() || !$query->is_main_query() || !$query->is_seach() )
    return;

  // Check if the search string contains only Latin/Common Unicode characters
  $match_result = preg_match( '/^[p{Latin}p{Common}]+$/u', $query->get( 's' ) );

  // If the search string only contains Latin/Common characters, let it continue
  if( 1 === $match_result )
    return;

  $query->set( 's', ' ' ); // Replace the non-latin search with an empty one
  $query->set( 'post__in', array(0) ); // Make sure no post is ever returned

  //TODO: Set up logic to display error message
}

add_action( 'pre_get_posts', 'wpse261038_validate_search_characters' );

顯示錯誤

實際顯示錯誤消息的方式在很大程度上取決於您的應用程序和主題的能力 – 有很多方法可以完成。如果您的主題在其搜索模板中調用 get_search_form(),則最簡單的解決方案可能是使用 pre_get_search_form 動作鈎子在搜索表單上方輸出錯誤:

function wpse261038_validate_search_characters( $query ) {
  // Leave admin, non-main query, and non-search queries alone
  if( is_admin() || !$query->is_main_query() || !$query->is_seach() )
    return;

  // Check if the search string contains only Latin/Common Unicode characters
  $match_result = preg_match( '/^[p{Latin}p{Common}]+$/u', $query->get( 's' ) );

  // If the search string only contains Latin/Common characters, let it continue
  if( 1 === $match_result )
    return;

  $query->set( 's', ' ' ); // Replace the non-latin search with an empty one
  $query->set( 'post__in', array(0) ); // Make sure no post is ever returned

  add_action( 'pre_get_search_form', 'wpse261038_display_search_error' );
}

add_action( 'pre_get_posts', 'wpse261038_validate_search_characters' );

function wpse261038_display_search_error() {
  echo '<div class="notice notice-error"><p>Your search could not be completed as it contains characters from non-Latin alphabets.<p></div>';
}

顯示錯誤消息的其他一些可能性包括:

  • 如果您的站點使用可以顯示 「flash」 或 「modal」 消息的 JavaScript(或者您自己添加這些功能),則添加一個邏輯來在設置特定變量時顯示 page-load 上的消息,然後添加一個 wp_enqueue_script 鈎子一個大於排列該 JavaScript 的 $priority,並使用 wp_localize_script()將該變量設置為包含錯誤消息。

  • 使用 wp_redirect()將用户發送到您選擇的 URL(此方法需要額外的頁面加載) 。

  • 設置一個 PHP 變量或調用一個方法,它將通知您的主題/插件有關錯誤,以便它可以在適當的時候顯示。

  • s 查詢變量設置為''而不是' ',並使用 page_id 代替 post__in,以返回您選擇的頁面。

  • 使用 loop_start 鈎子將含有錯誤的假 WP_Post 對象注入到查詢結果中 – 這絕對是一個醜陋的黑客,可能不符合您的特定主題,但它具有抑制”No Results” 消息的潛在可能的副作用。

  • 使用 template_include 過濾器掛鈎,在您的主題或插件中顯示您的錯誤,使用自定義的模板交換搜索模板。

沒有檢查有關的主題,很難確定你應該採用哪條路線。

參考文獻

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