問題描述

在管理區域 (wp-admin /users.php) 中列出的使用者頂部的搜尋表單受到限制,並且不搜尋所有使用者元欄位,例如生物,即時訊息手柄等。我還沒有找到一個可以新增的外掛。

有人知道一個外掛或一個可以建立的功能,可以擴充套件這個搜尋在_usermeta 資料庫中的所有日期 – 理想情況下甚至由外掛或函式建立的額外欄位。

最佳解決方案

嗨 @ user2041:

很明顯,如你所知,您需要透過修改用於搜尋的 WP_User_Search 類的例項中的值來修改執行的搜尋 (您可以在/wp-admin/includes/user.php 找到原始碼,如果您想學習的話) 。

WP_User_Search 物件

以下是搜尋 「TEST」 並且沒有任何其他可能影響到的外掛時,該物件的 print_r()與 WordPress 3.0.3 類似。

WP_User_Search Object
(
  [results] =>
  [search_term] => TEST
  [page] => 1
  [role] =>
  [raw_page] =>
  [users_per_page] => 50
  [first_user] => 0
  [last_user] =>
  [query_limit] =>  LIMIT 0, 50
  [query_orderby] =>  ORDER BY user_login
  [query_from] =>  FROM wp_users
  [query_where] =>  WHERE 1=1 AND (user_login LIKE '%TEST%' OR user_nicename LIKE '%TEST%' OR user_email LIKE '%TEST%' OR user_url LIKE '%TEST%' OR display_name LIKE '%TEST%')
  [total_users_for_query] => 0
  [too_many_total_users] =>
  [search_errors] =>
  [paging_text] =>
)

pre_user_search

要修改 WP_User_Search 物件的值,您將使用接收當前物件例項的'pre_user_search'鉤子; 我從該鉤子中呼叫 print_r()來訪問上面顯示的值。

您可以將以下示例複製到主題的 functions.php 檔案,或者您可以在 PHP 檔案中使用您正在編寫的外掛,除了可以在其他欄位上搜尋之外,還可以搜尋使用者描述。該功能修改了 $user_search 物件的 query_fromquery_where 屬性,您需要使用 SQL 才能理解。

仔細修改鉤子中的 SQL

yoursite_pre_user_search()函式中的程式碼假定沒有其他外掛在它之前修改了 query_where 子句; 如果另一個外掛已經修改了 where 子句,以便用"WHERE 1=1 AND ({$description_where} OR"替換'WHERE 1=1 AND ('不再工作,那麼這也將中斷。編寫一個強大的補丁比在這樣修改 SQL 時不能被其他外掛所破壞的難得多,但它是什麼。

在鉤子插入 SQL 時新增主要和後跟空格

另請注意,如果在 WordPress 中使用這樣的 SQL,總是一個好主意,包括" INNER JOIN {$wpdb->usermeta} ON "的前導和尾隨空格,否則您的 SQL 查詢可能包含以下"INNER"之前沒有空格,這當然會失敗:" FROM wp_postsINNER JOIN {$wpdb->usermeta} ON "

使用"{$wpdb->table_name"}而不是硬編碼表名稱

接下來一定要始終使用 $wpdb 屬性來引用表名,以防站點將表字首從'wp_'更改為其他。因此,最好是參考"{$wpdb->users}.ID"(雙引號,而不是單引號),而不是硬編碼"wp_users.ID"

僅當搜尋條件存在時才將查詢限制為

最後只能透過檢查 WP_User_Search 物件的 search_term 屬性來檢查可以測試的搜尋項時修改查詢。

'pre_user_search'yoursite_pre_user_search()功能

add_action('pre_user_search','yoursite_pre_user_search');
function yoursite_pre_user_search($user_search) {
  global $wpdb;
  if (!is_null($user_search->search_term)) {
    $user_search->query_from .= " INNER JOIN {$wpdb->usermeta} ON " .
      "{$wpdb->users}.ID={$wpdb->usermeta}.user_id AND " .
      "{$wpdb->usermeta}.meta_key='description' ";
    $description_where = $wpdb->prepare("{$wpdb->usermeta}.meta_value LIKE '%s'",
      "%{$user_search->search_term}%");
    $user_search->query_where = str_replace('WHERE 1=1 AND (',
      "WHERE 1=1 AND ({$description_where} OR ",$user_search->query_where);
  }
}

搜尋每個元 Key-Value 對需要一個 SQL JOIN

當然,WordPress 不允許您在 usermeta 欄位上搜尋的可能原因是每個人都向查詢新增了一個 SQL JOIN,並且具有太多連線的查詢可能會很慢。如果您真的需要搜尋許多欄位,那麼我將在 usermeta 中建立一個'_search_cache'欄位,將所有其他資訊收集到一個 usermeta 欄位中,以便只需要一個聯接即可搜尋。

Meta Keys 中的主要下劃線告訴 WordPress 不顯示

請注意,'_search_cache'的領先下劃線告訴 WordPress 這是一個內部值,而不是向使用者顯示的東西。

使用'profile_update''user_register'鉤子建立搜尋快取

因此,您需要分別在儲存使用者和註冊新使用者時觸發的'profile_update''user_register'。您可以抓住這些鉤子中的所有元鍵及其值 (但忽略具有序列化或 URL 編碼陣列的值),然後連線它們以使用'_search_cache'鍵儲存為一個長元值。

儲存後設資料為'|'定界 Key-Value 對

我決定抓住所有的關鍵名字和所有的值,並將它們與冒號 (“:”) 連線成一個大字串 (“:”),將鍵與值和垂直條 (“|”) 分開,這樣分離 key-value 對 (我將它們包裝成多個行,所以你可以他們沒有滾動到右邊):

nickname:mikeschinkel|first_name:mikeschinkel|description:This is my bio|
rich_editing:true|comment_shortcuts:false|admin_color:fresh|use_ssl:null|
wp_user_level:10|last_activity:2010-07-28 01:25:46|screen_layout_dashboard:2|
plugins_last_view:recent|screen_layout_post:2|screen_layout_page:2|
business_name:NewClarity LLC|business_description:WordPress Plugin Consulting|
phone:null|last_name:null|aim:null|yim:null|jabber:null|
people_lists_linkedin_url:null

使用 key:value 啟用 Meta 專業搜尋

按照我們所提供的關鍵字和值可以讓您進行諸如 「rich_editing:true」 的搜尋,以查詢具有豐富編輯的所有人,或者搜尋 「phone:null」 以找到沒有電話號碼的使用者。

但請注意搜尋人工製品

當然,使用這種技術可能會產生不必要的搜尋工件,例如搜尋”business”,並且每個人都將被列出。如果這是一個問題,那麼你可能不想使用這樣一個精心設計的快取。

'profile_update''user_register'yoursite_profile_update()功能

對於函式 yoursite_profile_update(),如上面的 yoursite_pre_user_search()可以複製到您的主題的 functions.php 檔案,或者您可以在 PHP 檔案中使用您正在編寫的外掛:

add_action('profile_update','yoursite_profile_update');
add_action('user_register','yoursite_profile_update');
function yoursite_profile_update($user_id) {
  $metavalues = get_user_metavalues(array($user_id));
  $skip_keys = array(
    'wp_user-settings-time',
    'nav_menu_recently_edited',
    'wp_dashboard_quick_press_last_post_id',
  );
  foreach($metavalues[$user_id] as $index => $meta) {
    if (preg_match('#^a:[0-9]+:{.*}$#ms',$meta->meta_value))
      unset($metavalues[$index]); // Remove any serialized arrays
    else if (preg_match_all('#[^=]+=[^&]&#',"{$meta->meta_value}&",$m)>0)
      unset($metavalues[$index]); // Remove any URL encoded arrays
    else if (in_array($meta->meta_key,$skip_keys))
      unset($metavalues[$index]); // Skip and uninteresting keys
    else if (empty($meta->meta_value)) // Allow searching for empty
      $metavalues[$index] = "{$meta->meta_key }:null";
    else if ($meta->meta_key!='_search_cache') // Allow searching for everything else
      $metavalues[$index] = "{$meta->meta_key }:{$meta->meta_value}";
  }
  $search_cache = implode('|',$metavalues);
  update_user_meta($user_id,'_search_cache',$search_cache);
}

更新了 yoursite_pre_user_search()功能,使單個 SQL JOIN 能夠搜尋所有有趣的元值

當然,對於 yoursite_profile_update()有任何影響,您將需要修改 yoursite_pre_user_search()以使用'_search_cache'元鍵而不是描述,我們在這裡 (與上述相同的注意事項):

add_action('pre_user_search','yoursite_pre_user_search');
function yoursite_pre_user_search($user_search) {
  global $wpdb;
  if (!is_null($user_search->search_term)) {
    $user_search->query_from .= " INNER JOIN {$wpdb->usermeta} ON " .
      "{$wpdb->users}.ID={$wpdb->usermeta}.user_id AND " .
      "{$wpdb->usermeta}.meta_key='_search_cache' ";
    $meta_where = $wpdb->prepare("{$wpdb->usermeta}.meta_value LIKE '%s'",
      "%{$user_search->search_term}%");
    $user_search->query_where = str_replace('WHERE 1=1 AND (',
      "WHERE 1=1 AND ({$meta_where} OR ",$user_search->query_where);
  }
}

次佳解決方案

我非常感謝 MikeSchinkel 的方法和上面的徹底解釋。這是 super-helpful 。我不能讓它為我工作,因為 pre_user_search 已被棄用,並沒有在 3.2 中實際工作。我試著用 pre_user_query 將其切換出去,但是也沒有。事情是,似乎 $ user_search-> search_term 不工作,所以我只是使用 $ _GET [‘s’] 。我做了一些駭客攻擊,並能在 3.2 中得到這個工作。您唯一需要設定的是可搜尋後設資料的陣列。

//Searching Meta Data in Admin
add_action('pre_user_query','yoursite_pre_user_search');
function yoursite_pre_user_search($user_search) {
    global $wpdb;
    if (!isset($_GET['s'])) return;

    //Enter Your Meta Fields To Query
    $search_array = array("customer_id", "postal_code", "churchorganization_name", "first_name", "last_name");

    $user_search->query_from .= " INNER JOIN {$wpdb->usermeta} ON {$wpdb->users}.ID={$wpdb->usermeta}.user_id AND (";
    for($i=0;$i<count($search_array);$i++) {
        if ($i > 0) $user_search->query_from .= " OR ";
            $user_search->query_from .= "{$wpdb->usermeta}.meta_key='" . $search_array[$i] . "'";
        }
    $user_search->query_from .= ")";
    $custom_where = $wpdb->prepare("{$wpdb->usermeta}.meta_value LIKE '%s'", "%" . $_GET['s'] . "%");
    $user_search->query_where = str_replace('WHERE 1=1 AND (', "WHERE 1=1 AND ({$custom_where} OR ",$user_search->query_where);
}

希望這有助於某人。

參考文獻

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