Cách tìm kiếm tất cả meta người dùng từ users.php trong quản trị viên


14

Biểu mẫu tìm kiếm ở đầu danh sách người dùng trong khu vực Quản trị viên (wp-admin / users.php) bị giới hạn và không tìm kiếm tất cả các trường meta của người dùng, chẳng hạn như bio, xử lý trình nhắn tin tức thời, v.v. đã có thể tìm thấy một plugin có thể thêm điều này.

Có ai biết về plugin hoặc chức năng mà tôi có thể tạo có thể mở rộng tìm kiếm này cho tất cả các ngày trong _usermeta DB - lý tưởng nhất là các trường bổ sung được tạo bởi plugin hoặc chức năng.

Câu trả lời:


24

Xin chào @ user2041:

Rõ ràng như bạn biết bạn cần sửa đổi tìm kiếm đã thực hiện bằng cách sửa đổi các giá trị trong thể hiện của WP_User_Searchlớp được sử dụng cho tìm kiếm (bạn có thể tìm mã nguồn tại /wp-admin/includes/user.phpnếu bạn muốn nghiên cứu về nó.)

các WP_User_Searchđối tượng

Đây là một print_r()đối tượng trông như thế nào với WordPress 3.0.3 khi tìm kiếm cụm từ " TEST" và không có bất kỳ plugin nào khác có thể ảnh hưởng đến nó:

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] => 
)

các pre_user_searchHook

Để sửa đổi các giá trị của WP_User_Searchđối tượng, bạn sẽ sử dụng 'pre_user_search'hook nhận thể hiện hiện tại của đối tượng; Tôi đã gọi print_r()từ bên trong cái móc đó để có quyền truy cập vào các giá trị mà tôi đã hiển thị ở trên.

Ví dụ sau mà bạn có thể sao chép vào functions.phptệp của chủ đề hoặc bạn có thể sử dụng trong tệp PHP cho plugin bạn đang viết thêm khả năng tìm kiếm trên mô tả của người dùng ngoài việc có thể tìm kiếm trên các trường khác. Hàm này sửa đổi query_fromvà các query_wherethuộc tính của $user_searchđối tượng mà bạn cần phải thoải mái với SQL để hiểu.

Sửa đổi cẩn thận SQL trong hook

Mã trong yoursite_pre_user_search()hàm giả định rằng không có plugin nào khác đã sửa đổi query_wheremệnh đề trước nó; nếu một plugin khác đã sửa đổi mệnh đề where sao cho thay thế 'WHERE 1=1 AND ('bằng "WHERE 1=1 AND ({$description_where} OR"không còn hoạt động thì điều này cũng sẽ bị hỏng. Việc viết một bổ sung mạnh mẽ không thể bị phá vỡ bởi một plugin khác khi sửa đổi SQL như thế này khó hơn nhiều, nhưng đó là những gì nó được.

Thêm không gian hàng đầu và lưu trữ khi chèn SQL vào móc

Cũng lưu ý rằng khi sử dụng SQL như thế này trong WordPress, luôn luôn nên bao gồm các khoảng trắng ở đầu và cuối như vậy " INNER JOIN {$wpdb->usermeta} ON "nếu không thì truy vấn SQL của bạn có thể chứa những thứ sau đây không có khoảng trắng trước "INNER"đó, tất nhiên sẽ thất bại : " FROM wp_postsINNER JOIN {$wpdb->usermeta} ON ".

Sử dụng "{$wpdb->table_name"}thay vì tên bảng mã hóa

Tiếp theo hãy chắc chắn luôn luôn sử dụng các $wpdbthuộc tính để tham chiếu tên bảng trong trường hợp trang web đã thay đổi tiền tố bảng từ 'wp_'một thứ khác. Vì vậy, tốt hơn là tham khảo "{$wpdb->users}.ID" (với dấu ngoặc kép, không phải là dấu ngoặc đơn) thay vì mã hóa cứng "wp_users.ID".

Giới hạn truy vấn chỉ khi thuật ngữ tìm kiếm tồn tại

Cuối cùng, chỉ sửa đổi truy vấn khi có cụm từ tìm kiếm mà bạn có thể kiểm tra bằng cách kiểm tra search_termthuộc tính của WP_User_Searchđối tượng.

Các yoursite_pre_user_search()chức năng cho'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);    
  }
}

Tìm kiếm mỗi cặp giá trị khóa Meta yêu cầu SQL JOIN

Tất nhiên, lý do có khả năng WordPress không cho phép bạn tìm kiếm trên các trường usermeta là vì mỗi người thêm một SQL JOINvào truy vấn và một truy vấn có quá nhiều phép nối thực sự có thể bị chậm. Nếu bạn thực sự cần tìm kiếm trên nhiều lĩnh vực thì tôi sẽ tạo một '_search_cache'trường trong usermeta thu thập tất cả các thông tin khác vào một trường usermeta để chỉ yêu cầu một người tham gia để tìm kiếm tất cả.

Các dấu gạch dưới hàng đầu trong Meta Keys bảo WordPress không hiển thị

Lưu ý rằng việc gạch dưới hàng đầu trong '_search_cache'nói với WordPress rằng đây là một giá trị nội bộ và không phải là thứ gì đó sẽ hiển thị cho người dùng.

Tạo Cache tìm kiếm với 'profile_update''user_register'móc

Vì vậy, bạn sẽ cần nối cả hai 'profile_update''user_register'được kích hoạt để lưu người dùng và đăng ký người dùng mới, tương ứng. Bạn có thể lấy tất cả các khóa meta và giá trị của chúng trong các móc đó (nhưng bỏ qua các khóa có giá trị được tuần tự hóa hoặc mảng được mã hóa URL) và sau đó ghép chúng lại để lưu trữ dưới dạng một giá trị meta dài bằng '_search_cache'khóa.

Lưu trữ Meta dưới dạng '|'các cặp giá trị khóa được phân tách

Tôi quyết định lấy tất cả các tên khóa và tất cả các giá trị của chúng và ghép chúng thành một chuỗi lớn bằng dấu hai chấm (":") tách các khóa khỏi các giá trị và các thanh dọc ("|") tách các cặp giá trị khóa như thế này (I Chúng đã quấn chúng trên nhiều dòng để bạn có thể cuộn chúng sang bên phải):

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

Cho phép tìm kiếm chuyên biệt trên Meta bằng cách sử dụng key:value

Thêm khóa và giá trị như chúng tôi đã làm cho phép bạn thực hiện các tìm kiếm như " rich_editing:true" để tìm mọi người có chỉnh sửa phong phú hoặc tìm kiếm " phone:null" để tìm những người không có số điện thoại.

Nhưng hãy coi chừng các tạo phẩm tìm kiếm

Tất nhiên sử dụng kỹ thuật này sẽ tạo ra các tạo phẩm tìm kiếm không mong muốn như tìm kiếm "doanh nghiệp" và mọi người sẽ được liệt kê. Nếu đây là một vấn đề thì bạn có thể không muốn sử dụng bộ đệm phức tạp như vậy.

Các yoursite_profile_update()chức năng cho 'profile_update''user_register'

Đối với chức năng yoursite_profile_update(), như yoursite_pre_user_search()trên có thể được sao chép vào functions.phptệp chủ đề của bạn hoặc bạn có thể sử dụng trong tệp PHP cho plugin bạn đang viết:

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()Chức năng được cập nhật cho phép một SQL duy nhất JOINđể tìm kiếm tất cả các giá trị meta thú vị

Tất nhiên yoursite_profile_update()để có bất kỳ hiệu ứng nào, bạn sẽ cần sửa đổi yoursite_pre_user_search()để sử dụng '_search_cache'khóa meta thay vì mô tả mà chúng tôi có ở đây (với cùng một cảnh báo như đã đề cập ở trên):

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 Tuyệt vời, trả lời thấu đáo! Đây là một trong nhiều lần trên trang web này, nơi tôi muốn tôi có thể đưa ra nhiều câu trả lời cho câu trả lời được nghiên cứu kỹ lưỡng cho câu hỏi không có chứng khoán.
MathSmath

Cảm ơn @MathSmath - Học hỏi rằng mọi người đánh giá cao nó là điều giúp tôi tiếp tục. :)
MikeSchinkel

Mike, cảm ơn vì câu trả lời thấu đáo! Tôi sẽ làm việc này với chủ đề của tôi sau hôm nay và xem ai sẽ đi.
John Chandler

Mike, chúng ta gần rồi, nhưng ..! Rõ ràng điều này đang đưa tôi ra khỏi sự khởi đầu đúng đắn. Sử dụng một trong hai chức năng duy nhất mà bạn đề cập trước tiên hoặc hai chức năng để sử dụng profile_update đang hoạt động về khả năng tìm kiếm và nhận được kết quả phù hợp. Thật không may, các chức năng này đang gây rối với danh sách khi tôi lần đầu tiên kéo người dùng.php (không có thuật ngữ tìm kiếm nào được chỉ định). Nó không hiển thị tất cả người dùng. Khi tôi nhấp vào bộ lọc Tất cả, nó chỉ hiển thị hai (bốn trong số đó), một trong số đó là tôi và khi tôi nhấp vào bộ lọc Quản trị viên, nó không có bất kỳ người dùng nào - kể cả tôi! Có ý kiến ​​gì không?
John Chandler

Thêm một chút thông tin. Tôi đã chỉnh sửa chức năng đầu tiên để tìm kiếm một trường có tên là 'công ty' mà tôi đã thêm thông qua plugin thêm chi tiết người dùng. Nó hoạt động khi tôi tìm kiếm một người dùng có tên công ty. Nhưng, có vẻ như việc sắp xếp theo Tất cả, không có tìm kiếm, chỉ trả về hai kết quả có dữ liệu trong trường công ty và không trả về người dùng không có dữ liệu trong trường công ty.
John Chandler

4

Tôi thực sự đánh giá cao cách tiếp cận và giải thích kỹ lưỡng của MikeSchinkel ở trên. Điều này là siêu hữu ích. Tôi không thể làm cho nó hoạt động với tôi vì pre_user_search đã không được dùng nữa và không thực sự hoạt động trong 3.2. Tôi đã cố gắng chuyển nó ra bằng pre_user_query nhưng nó cũng không hoạt động. Vấn đề là, có vẻ như $ user_search-> search_term không hoạt động nữa nên tôi chỉ sử dụng $ _GET ['s']. Tôi đã thực hiện một số hack đi và có thể làm cho nó hoạt động trong 3.2. Điều duy nhất bạn cần đặt là mảng siêu dữ liệu có thể tìm kiếm của bạn.

//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);    
}

Hy vọng điều này sẽ giúp ai đó.


Có ai có bất kỳ kinh nghiệm gần đây với bất kỳ điều này? Cá nhân, tôi không thể làm cho bất kỳ đoạn mã nào trong số này hoạt động, kể cả những đoạn mã mới nhất. Tôi đã thử một số tùy chọn khác, nhưng đã tìm thấy vấn đề với phân trang kết quả .
Robert Andrew


1

Đây là một giải pháp cho phiên bản mới nhất của wordpress.

add_action( 'pre_user_query', 'yoursite_pre_user_search'  );
    function yoursite_pre_user_search( $query ) {
        $query->query_where .= "YOUR QUERY '" . str_replace("*", "%", $query->query_vars[ 'search' ] ) . "')";
    }

-1

Đây là những gì tôi đã đưa ra cho WordPress 4.7.1, bổ sung tìm kiếm ký tự đại diện cho tất cả dữ liệu meta của người dùng.


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

    if( empty($_REQUEST['s']) ){return;}
    $query->query_from .= ' LEFT JOIN '.$wpdb->usermeta.' ON '.$wpdb->usermeta.'.user_id = '.$wpdb->users.'.ID';
    $query->query_where = "WHERE 1=1 AND (user_login LIKE '%".$_REQUEST['s']."%' OR ID = '".$_REQUEST['s']."' OR meta_value LIKE '%".$_REQUEST['s']."%')";
    return $query;
}

Về cơ bản, chúng tôi chỉ tham gia bảng người dùng và bảng user_meta trên id người dùng và xây dựng lại mệnh đề WHERE để bao gồm tìm kiếm trên cột meta_value.


1
Những gì bạn đang đề nghị ở đây là rất nguy hiểm ! Bạn không bao giờ nên vượt qua bất cứ thứ gì được cung cấp bởi người dùng vào DB. Họ có thể bỏ các bảng của bạn, chiếm quyền điều khiển cơ sở dữ liệu của bạn, xem SQL tiêm như cụm từ tìm kiếm, hoặc chỉ mã hóa tất cả dữ liệu của bạn. Thực hiện "%".like_escape( $_GET['s'] )."%"thay thế. Điều tương tự cũng xảy ra với tất cả các dữ liệu người dùng khác cung cấp . Khác trường tìm kiếm của bạn trở thành một cổng mở cho dữ liệu của bạn.
kaiser
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.