Как искать все мета-данные пользователей из users.php в админ


Форма поиска в верхней части списка пользователей в административной области (wp-admin/users.php ) ограничен и не выполняет поиск по всем мета-полям пользователя, таким как биография, дескрипторы мгновенных сообщений и т.д. Я не смог найти плагин, который мог бы это добавить.

Знает ли кто-нибудь о плагине или функции, которые я мог бы создать, которые могли бы расширить этот поиск по всей дате в базе данных _usermeta - в идеале, даже дополнительные поля, создаваемые плагином или функцией.

Author: hakre, 2010-12-22

5 answers

Привет@пользователь2041:

Очевидно, как вы знаете, вам нужно изменить выполняемый поиск, что вы можете сделать, изменив значения в экземпляре класса 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', который получает текущий экземпляр объекта; Я вызвал print_r() из этого крючка, чтобы получить доступ к его значениям, которые я показал выше.

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

Тщательное изменение SQL в крючках

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

Добавляйте начальные и конечные пробелы при вставке SQL в крючки

Также обратите внимание, что при использовании SQL, подобного этому, в WordPress всегда рекомендуется включать начальные и конечные пробелы, такие как " 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".

Ограничьте запрос Только Тем, что Существуют условия поиска

Наконец, следует изменять запрос только при наличии поискового запроса, который вы можете проверить, проверив свойство 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 не позволяет вам выполнять поиск по полям usermeta, заключается в том, что каждый из них добавляет 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(), позволяющая использовать один 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);
  }
}
 24
Author: MikeSchinkel, 2010-12-24 00:29:28

Я действительно оценил подход Микешинкеля и подробное объяснение выше. Это было очень полезно. Я не мог заставить его работать на меня, так как 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);    
}

Надеюсь, это кому-нибудь поможет.

 6
Author: David, 2011-09-10 06:25:05

К вашему сведению, для людей, которые ищут по этой теме (как настроить поисковый запрос на панели пользователя) и находят эту отличную страницу, WP_User_Search устарел по WP_User_Query с 3.1: http://codex.wordpress.org/Class_Reference/WP_User_Query .

 1
Author: FredHead, 2011-09-08 18:53:19

Вот решение для новейшей версии 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
Author: Patrik Grinsvall, 2012-08-08 14:03:25

Это то, что я придумал для 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;
}

В основном мы просто объединяем таблицы users и user_meta в идентификаторе пользователя и перестраиваем предложение WHERE, чтобы включить поиск в столбце meta_value.

 -1
Author: wagontrader, 2017-01-22 18:30:07