Як шукати всі мета користувача з users.php в адміністраторі


14

Форма пошуку вгорі списку користувачів в області адміністратора (wp-admin / users.php) обмежена і не здійснює пошук у всіх метаполях користувачів, таких як біо, обмін миттєвими повідомленнями тощо. Я не вдалося знайти плагін, який може додати це.

Хтось знає плагін або функцію, яку я міг би створити, що може розширити цей пошук за всіма датами в БД _usermeta - в ідеалі навіть додаткові поля, створені плагіном або функцією.

Відповіді:


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_searchHook

Для зміни значень WP_User_Searchоб’єкта ви будете використовувати 'pre_user_search'гачок, який отримує поточний екземпляр об'єкта; Я закликав print_r()всередині цього гака, щоб отримати доступ до його значень, які я відображав вище.

Наступний приклад, який ви можете скопіювати у functions.phpфайл вашої теми або ви можете використовувати у файлі PHP для плагіна, який ви пишете, додає можливість пошуку за описом користувача а також можливість пошуку в інших полях. Функція змінює query_fromі query_whereвластивості $user_searchоб'єкта, які вам потрібні, щоб зручно розуміти SQL.

Ретельна зміна SQL в гачках

Код у yoursite_pre_user_search()функції передбачає, що жоден інший плагін не змінив query_whereположення до нього; якщо інший плагін змінив пункт де таке, що замінює'WHERE 1=1 AND (' з "WHERE 1=1 AND ({$description_where} OR"більше не працює , то це порушить теж. Набагато складніше написати надійне доповнення, яке не може бути зламане іншим плагіном при зміні SQL, як це, але воно є таким.

Додайте провідні та кінцеві простори, коли вставляєте SQL в гачки

Також зверніть увагу , що при використанні SQL , як це в WordPress , це завжди гарна ідея , щоб включати в себе початкові і кінцеві пробіли такої з " INNER JOIN {$wpdb->usermeta} ON "іншим ваш запит може містити наступну команду, де немає простору перед тим "INNER", що буде, звичайно , НЕ в змозі : " FROM wp_postsINNER JOIN {$wpdb->usermeta} ON ".

Використовуйте "{$wpdb->table_name"}замість імен таблиць жорсткого кодування

Далі обов'язково використовуйте $wpdbвластивості для посилання на назви таблиць у випадку, якщо сайт змінив префікс таблиці 'wp_'на щось інше. Таким чином, краще звернутися до них "{$wpdb->users}.ID" (з подвійними цитатами, а не поодинокими) замість жорсткого кодування "wp_users.ID".

Обмежте запит лише тоді, коли існують пошукові терміни

Нарешті, слід змінювати запит лише тоді, коли є пошуковий термін, який ви можете перевірити, перевіривши 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);    
  }
}

Для пошуку кожної пари мета-значення потрібен SQL JOIN

Звичайно, ймовірна причина, що WordPress не дозволяє шукати на полях користувачів, полягає в тому, що кожен додає SQL JOINдо запиту, а запит із занадто великою кількістю приєднань справді може бути повільним. Якщо вам дійсно потрібно здійснити пошук у багатьох полях, тоді я створив би '_search_cache'поле в usermeta, яке збирає всю іншу інформацію в одне поле usermeta, щоб вимагати лише одного об’єднання для пошуку в ньому.

Провідні підкреслення в мета-ключах говорять WordPress не відображатись

Зауважте, що підкреслення підкреслює в '_search_cache'WordPress, що це внутрішнє значення, а не те, що коли-небудь відображатиметься користувачеві.

Створіть кеш-пошук за допомогою 'profile_update'і 'user_register'гачок

Таким чином, вам потрібно буде підключити 'profile_update'і 'user_register'те, і інше, що спрацьовує при збереженні користувача та реєстрації нового користувача відповідно. Ви можете схопити всі мета-ключі та їх значення у цих гачках (але опустити ті зі значеннями, які є серіалізованими або масивами, кодованими URL-адресою), а потім з'єднати їх у сховище як одне довге мета-значення, використовуючи'_search_cache' ключа.

Зберігайте мета як '|'розділені пари ключових значень

Я вирішив схопити всі ключові імена та всі їхні значення та об'єднати їх у одну велику рядок із двокрапками (":"), що відокремлюють ключі від значень та вертикальні смуги ("|"), розділяючи пари ключових значень, як це (я обернув їх через кілька ліній, щоб ви могли їх прокручувати праворуч):

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

Додавання ключа та значень, як ми робили, дозволяє вам здійснювати пошук типу " 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()функція, що включає єдиний SQLJOIN для пошуку всіх цікавих мета-значень

Звичайно, 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 Чудова, ретельна відповідь! Це один з багатьох разів на цьому веб-сайті, де я хотів би дати кілька заявок за таку добре вивчену відповідь на питання, що не є акціями.
MathSmath

Спасибі @MathSmath - Навчання, що люди цінують це - те, що мене змушує йти. :)
MikeSchinkel

Майк, дякую за ретельну відповідь! Я опрацюю це над своєю темою пізніше сьогодні і побачу, хто це йде.
Джон Чендлер

Майк, ми близькі, але ..! Зрозуміло, що це відводить мене від правильного старту. Використання або однієї з функцій, яку ви спочатку згадуєте, або двох функцій для використання профілю_обновлення працює з точки зору можливості пошуку та отримання належних результатів. На жаль, ці функції псуються з лістингом, коли я вперше підтягнув users.php (який не вказав пошуковий термін). Він показує не всім користувачам. Коли я натискаю на фільтр "Усі", він показує лише два (з чотирьох), один з яких - це я, а коли я натискаю на фільтр "Адміністратори", він не має жодних користувачів - навіть я! Будь-які ідеї?
Джон Чендлер

Ще трохи інформації. Я відредагував першу функцію пошуку в полі під назвою "компанія", яке я додав через плагін додаткових даних про користувача. Він працює, коли я шукаю користувача з назвою компанії. Але виявляється, що сортування за всіма, без пошуку, повертає лише два результати, які мають дані в полі компанії, а не повертає користувачів, які не мають даних у полі компанії.
Джон Чендлер

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

Сподіваюся, це комусь допомагає.


Хтось має останній досвід з цим? Особисто я не можу отримати жоден із цих бітів коду, включаючи останні. Я спробував деякі інші варіанти, але виявив проблеми з розбиттям результатів .
Роберт Ендрюс


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'] )."%"замість цього. Те саме стосується всіх інших наданих користувачем даних . Інакше поле пошуку стає відкритим шлюзом для ваших даних.
кайзер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.