วิธีค้นหาเมตาผู้ใช้ทั้งหมดจาก users.php ในผู้ดูแลระบบ


14

แบบฟอร์มการค้นหาที่ด้านบนของรายชื่อผู้ใช้ในพื้นที่ผู้ดูแลระบบ (wp-admin / users.php) มี จำกัด และไม่ค้นหาเขตข้อมูลเมตาของผู้ใช้ทั้งหมดเช่นชีวภาพตัวจัดการเมสเซนเจอร์ด่วน ฯลฯ ฉันไม่ได้ สามารถค้นหาปลั๊กอินที่สามารถเพิ่มสิ่งนี้ได้

มีใครรู้บ้างเกี่ยวกับปลั๊กอินหรือฟังก์ชั่นที่ฉันสามารถสร้างที่สามารถขยายการค้นหานี้สำหรับวันที่ทั้งหมดใน _usermeta DB ได้ - โดยเฉพาะอย่างยิ่งเขตข้อมูลพิเศษที่สร้างโดยปลั๊กอินหรือฟังก์ชั่น

คำตอบ:


24

สวัสดี@ user2041:

เห็นได้ชัดว่าคุณจำเป็นต้องแก้ไขการค้นหาที่ดำเนินการซึ่งคุณสามารถทำได้โดยการปรับเปลี่ยนค่าในอินสแตนซ์ของWP_User_Searchคลาสที่ใช้สำหรับการค้นหา(คุณสามารถค้นหาซอร์สโค้ดได้ที่/wp-admin/includes/user.phpหากคุณต้องการศึกษา)

WP_User_Searchวัตถุ

นี่คือลักษณะprint_r()ของวัตถุนั้นด้วย WordPress 3.0.3 เมื่อค้นหาคำว่า" TEST"และไม่มีปลั๊กอินอื่น ๆ ที่อาจส่งผลกระทบต่อ:

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'hook ที่รับอินสแตนซ์ปัจจุบันของวัตถุ ฉันโทรprint_r()จากภายในเบ็ดนั้นเพื่อเข้าถึงค่าที่ฉันแสดงด้านบน

ตัวอย่างต่อไปนี้ซึ่งคุณสามารถคัดลอกไปยังfunctions.phpไฟล์ธีมของคุณหรือคุณสามารถใช้ในไฟล์ PHP สำหรับปลั๊กอินที่คุณกำลังเขียนเพิ่มความสามารถในการค้นหาคำอธิบายของผู้ใช้นอกเหนือจากการค้นหาในฟิลด์อื่น ๆ ฟังก์ชั่นปรับเปลี่ยนquery_fromและquery_whereคุณสมบัติของ$user_searchวัตถุที่คุณต้องคุ้นเคยกับ SQL ที่จะเข้าใจ

การแก้ไข SQL ใน hooks อย่างระมัดระวัง

รหัสในyoursite_pre_user_search()ฟังก์ชั่นสันนิษฐานว่าไม่มีปลั๊กอินอื่นที่ได้แก้ไขquery_whereอนุประโยคก่อนหน้า หากปลั๊กอินอื่นมีการแก้ไขส่วนคำสั่งที่แทนที่'WHERE 1=1 AND ('ด้วย"WHERE 1=1 AND ({$description_where} OR"ไม่ทำงานอีกต่อไปนี้จะแตกเกินไป มันยากกว่ามากในการเขียนส่วนเสริมที่แข็งแกร่งซึ่งไม่สามารถแยกได้โดยปลั๊กอินอื่นเมื่อทำการแก้ไข SQL เช่นนี้ แต่มันคือสิ่งที่มันเป็น

เพิ่มช่องว่างนำหน้าและต่อท้ายเมื่อแทรก SQL ใน Hooks

นอกจากนี้ยังทราบว่าเมื่อใช้ SQL เช่นนี้ใน WordPress ก็มักจะเป็นความคิดที่ดีที่จะรวมชั้นนำและช่องว่างต่อท้ายเช่นมี" INNER JOIN {$wpdb->usermeta} ON "ตัวเลขที่มิฉะนั้นแบบสอบถาม SQL ของคุณอาจมีดังต่อไปนี้ที่มีพื้นที่ไม่ก่อนที่จะล้มเหลวของหลักสูตร:"INNER"" FROM wp_postsINNER JOIN {$wpdb->usermeta} ON "

ใช้"{$wpdb->table_name"}แทนชื่อตาราง Hardcoding

ถัดไปอย่าลืมใช้$wpdbคุณสมบัติเพื่ออ้างอิงชื่อตารางในกรณีที่ไซต์เปลี่ยนคำนำหน้าตารางจาก'wp_'เป็นอย่างอื่น ดังนั้นมันจะดีกว่าที่จะอ้างถึง"{$wpdb->users}.ID" (ที่มีราคาคู่ไม่ได้คนเดียว)แทน "wp_users.ID"hardcoding

จำกัด การค้นหาเฉพาะเมื่อมีคำค้นหาอยู่

สุดท้ายคือปรับเปลี่ยนการสืบค้นเฉพาะเมื่อมีข้อความค้นหาที่คุณสามารถทดสอบได้โดยการตรวจสอบsearch_termคุณสมบัติของWP_User_Searchวัตถุ

yoursite_pre_user_search()ฟังก์ชั่นสำหรับ'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);    
  }
}

การค้นหาคู่คีย์ - ค่า Meta แต่ละคู่ต้องใช้ SQL JOIN

แน่นอนว่าสาเหตุที่ WordPress ไม่อนุญาตให้คุณค้นหาในช่อง usermeta ก็คือแต่ละคนจะเพิ่ม SQL JOINลงในคิวรีและเพื่อให้คิวรีที่มีตัวเชื่อมมากเกินไปนั้นอาจช้าได้อย่างแน่นอน หากคุณต้องการค้นหาในหลาย ๆ ฟิลด์ฉันจะสร้าง'_search_cache'เขตข้อมูลใน usermeta ที่รวบรวมข้อมูลอื่น ๆ ทั้งหมดลงในช่อง usermeta หนึ่งช่องเพื่อขอให้เข้าร่วมเพียงครั้งเดียวเพื่อค้นหาทุกอย่าง

ขีดเส้นใต้ชั้นนำใน Meta Keys บอกว่า WordPress จะไม่แสดง

โปรดทราบว่าการนำขีดเส้นใต้มา'_search_cache'บอกกับ WordPress ว่านี่เป็นค่าภายในและไม่ใช่สิ่งที่จะแสดงต่อผู้ใช้

สร้างแคชค้นหาด้วย'profile_update'และ'user_register'hooks

ดังนั้นคุณจะต้องขอทั้งสองอย่าง'profile_update'และ'user_register'สิ่งนี้จะถูกกระตุ้นให้บันทึกผู้ใช้และลงทะเบียนผู้ใช้ใหม่ตามลำดับ คุณสามารถคว้าเมตาคีย์และค่าทั้งหมดใน hooks เหล่านั้น(แต่ไม่ใช้เมตาที่มีค่าที่ถูกทำให้เป็นลำดับหรือ URL ที่เข้ารหัสแบบอาร์เรย์)จากนั้นทำการเชื่อมต่อเมตาดาต้าเหล่านั้นเพื่อจัดเก็บเป็นเมตาดาต้ายาว'_search_cache'

จัดเก็บ Meta เป็น'|'คู่คีย์ - ค่าที่คั่น

ฉันตัดสินใจที่จะคว้าชื่อคีย์ทั้งหมดและค่าทั้งหมดของพวกเขาและต่อกันเป็นสตริงใหญ่ที่มี colons (":") แยกคีย์ออกจากค่าและแถบแนวตั้ง ("|") คั่นคู่คีย์ - ค่าเช่นนี้(ฉัน มีการห่อหลายบรรทัดเพื่อให้คุณสามารถทำได้โดยไม่ต้องเลื่อนไปทางขวา):

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

เปิดใช้การค้นหาแบบพิเศษเกี่ยวกับการใช้ Meta key:value

การเพิ่มคีย์และค่าตามที่เราอนุญาตให้คุณทำการค้นหาเช่น " rich_editing:true" เพื่อค้นหาทุกคนที่มีการแก้ไขที่หลากหลายหรือค้นหา " phone:null" เพื่อค้นหาสิ่งที่ไม่มีหมายเลขโทรศัพท์

แต่ระวังสิ่งประดิษฐ์ค้นหา

แน่นอนว่าการใช้เทคนิคนี้จะสร้างสิ่งประดิษฐ์การค้นหาที่ไม่ต้องการเช่นการค้นหา"ธุรกิจ"และทุกคนจะได้รับการจดทะเบียน หากเป็นปัญหาคุณอาจไม่ต้องการใช้แคชที่ซับซ้อนเช่นนี้

yoursite_profile_update()ฟังก์ชั่นสำหรับการ'profile_update'และ'user_register'

สำหรับฟังก์ชั่นดัง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เพื่อค้นหาค่า Meta ที่น่าสนใจทั้งหมด

แน่นอนว่า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 ยอดเยี่ยมตอบอย่างละเอียด! นี่เป็นหนึ่งในหลาย ๆ ครั้งบนเว็บไซต์นี้ที่ฉันหวังว่าฉันจะมอบ upvotes หลายครั้งสำหรับคำตอบที่ดีสำหรับคำถามที่ไม่ใช่สต็อก
MathSmath

Thanks @MathSmath - เรียนรู้ว่าผู้คนชื่นชมมันเป็นสิ่งที่ทำให้ฉันไป :)
MikeSchinkel

ไมค์ขอบคุณสำหรับคำตอบอย่างละเอียด! ฉันจะทำสิ่งนี้เป็นธีมของฉันในวันนี้และดูว่าใครจะไป
John Chandler

ไมค์พวกเราสนิทกันแล้ว .. ! เห็นได้ชัดว่านี่เป็นการเริ่มต้นที่ถูกต้องให้กับฉัน การใช้ทั้งฟังก์ชั่นเดียวที่คุณพูดถึงก่อนหน้านี้หรือทั้งสองฟังก์ชั่นเพื่อใช้งาน profile_update กำลังทำงานในแง่ของความสามารถในการค้นหาและรับผลลัพธ์ที่เหมาะสม น่าเสียดายที่ฟังก์ชั่นเหล่านี้ยุ่งกับรายชื่อเมื่อฉันดึง users.php ขึ้นมาครั้งแรก (ซึ่งไม่ได้ระบุข้อความค้นหา) มันไม่ได้แสดงผู้ใช้ทั้งหมด เมื่อฉันคลิกที่ตัวกรองทั้งหมดจะแสดงเพียงสอง (จากสี่) ซึ่งหนึ่งในนั้นคือฉันและเมื่อฉันคลิกที่ตัวกรองผู้ดูแลระบบจะไม่ใช้ผู้ใช้ - ไม่ใช่แม้แต่ฉัน! ความคิดใด ๆ
John Chandler

ข้อมูลเพิ่มเติมเล็กน้อย ฉันแก้ไขฟังก์ชันแรกเพื่อค้นหาฟิลด์ที่เรียกว่า 'บริษัท ' ซึ่งฉันเพิ่มผ่านปลั๊กอินรายละเอียดผู้ใช้เพิ่มเติม มันทำงานได้เมื่อฉันค้นหาผู้ใช้ด้วยชื่อ บริษัท แต่ดูเหมือนว่าการเรียงลำดับโดยทั้งหมดโดยไม่มีการค้นหาจะส่งคืนผลลัพธ์สองรายการที่มีข้อมูลในฟิลด์ บริษัท เท่านั้นและไม่ส่งคืนผู้ใช้ที่ไม่มีข้อมูลในฟิลด์ บริษัท
John Chandler

5

ฉันชื่นชมวิธีการของ MikeSchinkel และคำอธิบายอย่างละเอียดข้างต้น สิ่งนี้มีประโยชน์มาก ฉันไม่สามารถทำงานให้ฉันได้เพราะ 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);    
}

หวังว่านี่จะช่วยใครซักคน


ไม่มีใครมีประสบการณ์เมื่อเร็ว ๆ นี้กับสิ่งนี้หรือไม่? โดยส่วนตัวแล้วฉันไม่สามารถรับบิตของรหัสเหล่านี้ได้รวมถึงอันล่าสุด ฉันได้ลองตัวเลือกอื่น ๆ บางอย่าง แต่ได้พบปัญหาเกี่ยวกับผลการแบ่งหน้า
Robert Andrews

1

FYI สำหรับคนค้นหาในหัวข้อนี้ (วิธีการปรับการค้นหาของผู้ใช้แผง) และการหาหน้ายอดเยี่ยมนี้ WP_User_Search ได้รับการคัดค้านจาก WP_User_Query เป็น 3.1: http://codex.wordpress.org/Class_Reference/WP_User_Query


1

นี่คือทางออกของ 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

นี่คือสิ่งที่ฉันใช้กับ WordPress 4.7.1 ซึ่งเพิ่มการค้นหาไวด์การ์ดในข้อมูลเมตาของผู้ใช้ทั้งหมด


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

โดยพื้นฐานแล้วเราเพิ่งเข้าร่วมผู้ใช้และตาราง user_meta ในรหัสผู้ใช้และสร้างคำสั่งย่อย WHERE ใหม่เพื่อรวมการค้นหาในคอลัมน์ meta_value


1
สิ่งที่คุณแนะนำที่นี่มีอันตรายมาก ! คุณไม่ควรผ่านสิ่งที่ผู้ใช้จัดหาให้ในฐานข้อมูล พวกเขาสามารถวางตารางของคุณจี้ฐานข้อมูลของคุณ - ดูการฉีด SQL เป็นวลีค้นหาหรือเพียงแค่เข้ารหัสข้อมูลทั้งหมดของคุณ ทำ"%".like_escape( $_GET['s'] )."%"แทน เดียวกันจะไปสำหรับข้อมูลของผู้ใช้บริการที่มีให้คนอื่นมิฉะนั้นช่องค้นหาของคุณจะกลายเป็นประตูเปิดสู่ข้อมูลของคุณ
ไกเซอร์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.