WordPress 自訂使用者搜尋功能實作筆記

前言

在 WordPress 中,預設的使用者搜尋功能僅能查詢固定欄位如使用者名稱或電子郵件,無法搜尋自定義欄位資料。當網站需要透過電話號碼等自定義欄位進行搜尋時,預設功能就顯得不足。本篇筆記將示範如何利用 WordPress 的鉤子擴充後台使用者搜尋功能,支援自定義欄位的搜尋。

為什麼需要自訂使用者搜尋?

WordPress 預設不支援透過自定義欄位搜尋使用者資料,對於擁有大量自定義欄位的網站管理者來說,這是一大限制。透過自訂搜尋功能,可以讓管理者在後台使用者列表中,直接搜尋像是「reg_phone」這類的自定義欄位,提升管理效率。

自訂使用者搜尋的程式碼範例

以下程式碼示範如何使用 pre_user_query 動作鉤子,修改後台使用者查詢的 SQL,加入對自定義欄位 reg_phone 的搜尋支援:

add_action('pre_user_query', 'project_pre_user_search');
function project_pre_user_search($query) {
    global $wpdb;
    global $pagenow;

    // 僅在後台使用者列表頁且有搜尋字串時執行
    if (is_admin() && 'users.php' === $pagenow && !empty($_REQUEST['s'])) {
        // 過濾搜尋字串,避免 SQL 注入
        $search_term = esc_sql($_REQUEST['s']);

        // 加入 DISTINCT 避免重複
        $query->query_fields = 'DISTINCT ' . $query->query_fields;
        // 連接 usermeta 表以搜尋自定義欄位
        $query->query_from .= " LEFT JOIN {$wpdb->usermeta} ON {$wpdb->usermeta}.user_id = {$wpdb->users}.ID";
        // 新增搜尋條件,模糊比對 reg_phone 欄位
        $query->query_where .= $wpdb->prepare(
            " OR ({$wpdb->usermeta}.meta_key = 'reg_phone' AND {$wpdb->usermeta}.meta_value LIKE %s)",
            '%' . $search_term . '%'
        );
    }
    return $query;
}

程式碼解說

  1. 動作鉤子(Action Hook):使用 pre_user_query 在查詢執行前修改 SQL。
  2. 後台頁面檢查:確保只在後台使用者列表頁(users.php)執行。
  3. 搜尋關鍵字過濾:用 esc_sql() 避免 SQL 注入風險。
  4. 連接使用者欄位表:透過 LEFT JOIN 連接 usermeta 表。
  5. 新增搜尋條件:在 WHERE 子句加入對 reg_phone 欄位的模糊搜尋。

如何使用這段程式碼?

  1. 將程式碼加入主題的 functions.php 或自訂外掛中。
  2. 確認已有名為 reg_phone 的自定義使用者欄位,且欄位中有可搜尋資料。
  3. 進入 WordPress 後台「使用者」頁面。
  4. 在搜尋框輸入關鍵字,即可搜尋 reg_phone 欄位的匹配資料。

此功能的優點

  • 靈活性:支援搜尋非預設欄位的自定義資料。
  • 安全性:使用 WordPress 原生函數處理輸入,降低風險。
  • 可擴展性:可依需求修改支援更多自定義欄位。

完整程式碼

add_action('pre_user_query', 'project_pre_user_search');
function project_pre_user_search($query) {
    global $wpdb;
    global $pagenow;

    if (is_admin() && 'users.php' === $pagenow && !empty($_REQUEST['s'])) {
        $search_term = esc_sql($_REQUEST['s']);

        $query->query_fields = 'DISTINCT ' . $query->query_fields;
        $query->query_from .= " LEFT JOIN {$wpdb->usermeta} ON {$wpdb->usermeta}.user_id = {$wpdb->users}.ID";
        $query->query_where .= $wpdb->prepare(
            " OR ({$wpdb->usermeta}.meta_key = 'reg_phone' AND {$wpdb->usermeta}.meta_value LIKE %s)",
            '%' . $search_term . '%'
        );
    }
    return $query;
}