web-dev-qa-db-fra.com

Comment rechercher toutes les méta d'utilisateurs à partir de users.php dans l'administrateur

Le formulaire de recherche situé en haut de la liste des utilisateurs dans la zone d'administration (wp-admin/users.php) est limité et ne recherche pas dans tous les champs de méta de l'utilisateur, tels que la bio, les poignées de messagerie instantanée, etc. été capable de trouver un plugin qui peut ajouter cela.

Quelqu'un est-il au courant d'un plugin ou d'une fonction que je pourrais créer qui pourrait étendre cette recherche à toute la date de la base de données _usermeta - idéalement, même des champs supplémentaires créés par un plugin ou une fonction.

13
John Chandler

Bonjour @ user2041:

Clairement, comme vous le savez, vous devez modifier la recherche effectuée en modifiant les valeurs dans l’instance de la classe WP_User_Search utilisée pour la recherche (vous pouvez trouver le code source à /wp-admin/includes/user.php si vous souhaitez étudier it.)

L'objet WP_User_Search

Voici à quoi ressemble print_r() de cet objet avec WordPress 3.0.3 lors de la recherche du terme "TEST" et sans aucun autre plugin susceptible de l’affecter:

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

Le crochet pre_user_search

Pour modifier les valeurs de l'objet WP_User_Search, vous utiliserez le hook 'pre_user_search' qui reçoit l'instance actuelle de l'objet. J'ai appelé print_r() à partir de ce point d'ancrage pour accéder aux valeurs que j'ai affichées ci-dessus.

L'exemple suivant que vous pouvez copier dans le fichier functions.php de votre thème ou que vous pouvez utiliser dans un fichier PHP pour un plugin que vous écrivez ajoute la possibilité de rechercher sur la description de l'utilisateur en plus de pouvoir rechercher dans les autres champs. La fonction modifie les propriétés query_from et query_where de l'objet $user_search que vous devez maîtriser le langage SQL pour comprendre.

Attention à la modification de SQL dans les crochets

Le code de la fonction yoursite_pre_user_search() suppose qu'aucun autre plug-in n'a modifié la clause query_where auparavant. si un autre plugin a modifié la clause where, de telle sorte que le remplacement de 'WHERE 1=1 AND (' par "WHERE 1=1 AND ({$description_where} OR" ne fonctionne plus, cela se terminera également. Il est beaucoup plus difficile d'écrire un ajout robuste qui ne peut pas être cassé par un autre plugin lors de la modification de SQL de cette façon, mais c'est ce qu'il est.

Ajouter des espaces de début et de fin lors de l'insertion de SQL dans les crochets

Notez également que lorsque vous utilisez SQL de la sorte dans WordPress, c’est toujours une bonne idée d’inclure des espaces de début et de fin, par exemple avec " INNER JOIN {$wpdb->usermeta} ON ", sinon votre requête SQL pourrait contenir les éléments suivants dans lesquels il n’ya pas d’espace avant "INNER", ce qui bien sûr échouerait: " FROM wp_postsINNER JOIN {$wpdb->usermeta} ON ".

Utilisez "{$wpdb->table_name"} au lieu de noms de table codés en dur

Ensuite, veillez à toujours utiliser les propriétés $wpdb pour référencer les noms de table au cas où le site aurait changé le préfixe de table de 'wp_' à un autre nom. Il est donc préférable de faire référence à "{$wpdb->users}.ID" (avec des guillemets doubles, pas des guillemets simples) au lieu de coder en dur "wp_users.ID".

Limiter la requête à seulement quand les termes de recherche existent

Enfin, ne modifiez la requête que lorsqu'il existe un terme de recherche que vous pouvez tester en inspectant la propriété search_term de l'objet WP_User_Search.

La fonction yoursite_pre_user_search() pour '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);    
  }
}

La recherche de chaque paire méta-valeur nécessite un SQL JOIN

Bien sûr, la raison pour laquelle WordPress ne vous permet pas de rechercher des champs usermeta est que chacun ajoute une variable SQL JOIN à la requête et qu’une requête comportant trop de jointures peut effectivement être lente. Si vous avez vraiment besoin de rechercher dans plusieurs champs, je créerais un champ '_search_cache' dans usermeta qui rassemble toutes les autres informations dans un seul champ usermeta pour ne nécessiter qu'une seule jointure.

Les soulignés dans les méta-clés indiquent à WordPress de ne pas s'afficher

Notez que le tiret de soulignement dans '_search_cache' indique à WordPress qu'il s'agit d'une valeur interne et non d'un élément à afficher pour l'utilisateur.

Créer un cache de recherche avec les crochets 'profile_update' et 'user_register'

Il vous faudra donc relier les deux 'profile_update' et 'user_register' qui sont déclenchés lors de la sauvegarde d'un utilisateur et de l'enregistrement d'un nouvel utilisateur, respectivement. Vous pouvez récupérer toutes les clés méta et leurs valeurs dans les crochets (mais omettez celles avec des valeurs sérialisées ou des tableaux codés en URL) puis les concaténer pour les stocker sous la forme d'une méta-valeur longue à l'aide de la clé '_search_cache'.

Store Meta as '|' Paires clé-valeur délimitées

J'ai décidé de saisir tous les noms de clé et toutes leurs valeurs et de les concaténer en une grande chaîne avec des deux points (":") séparant les clés des valeurs et des barres verticales ("|") séparant les paires clé-valeur comme ceci (Je les ai mis sur plusieurs lignes pour pouvoir les faire défiler à droite):

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

Active les recherches spécialisées sur Meta à l'aide de key:value

Ajouter la clé et les valeurs comme nous vous avons permis de faire des recherches comme "rich_editing:true" pour trouver tous ceux qui ont une édition enrichie, ou de chercher "phone:null" pour trouver ceux qui n’ont pas de numéro de téléphone.

Mais attention aux artefacts de recherche

Bien sûr, l'utilisation de cette technique crée des artefacts de recherche éventuellement indésirables, tels que la recherche de "business" et tout le monde sera répertorié. Si cela pose un problème, vous ne voudrez peut-être pas utiliser un cache aussi élaboré.

La fonction yoursite_profile_update() pour 'profile_update' et 'user_register'

Pour la fonction yoursite_profile_update(), comme yoursite_pre_user_search() ci-dessus, vous pouvez le copier dans le fichier functions.php de votre thème ou vous pouvez l'utiliser dans un fichier PHP pour un plugin que vous écrivez:

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

Mise à jour yoursite_pre_user_search() Fonction permettant à un seul SQL JOIN de rechercher toutes les méta-valeurs intéressantes

Bien sûr, pour que yoursite_profile_update() ait un effet, vous devrez modifier yoursite_pre_user_search() pour utiliser la clé méta '_search_cache' à la place de la description, que nous avons ici (avec les mêmes mises en garde que mentionnées ci-dessus):

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
MikeSchinkel

J'ai vraiment apprécié l'approche de Mike Schchel et l'explication détaillée ci-dessus. C'était super utile. Je ne pouvais pas le faire fonctionner pour moi puisque pre_user_search est obsolète et ne fonctionne pas réellement dans 3.2. J'ai juste essayé de le remplacer avec pre_user_query mais cela n'a pas fonctionné non plus. Le problème, c'est qu'il semble que $ user_search-> search_term ne fonctionne plus, alors je viens d'utiliser $ _GET ['s']. J'ai fait du piratage et j'ai pu le faire fonctionner en 3.2. La seule chose que vous devez définir est votre tableau de métadonnées interrogeables.

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

J'espère que ça aide quelqu'un.

4
David

Voici une solution pour la nouvelle version de 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
Patrik Grinsvall

Pour votre information, pour les personnes cherchant sur ce sujet (comment ajuster la requête de recherche du panneau utilisateur) et trouver cette excellente page, WP_User_Search a été déconseillé par WP_User_Query à partir de 3.1: http://codex.wordpress.org/Class_Reference/WP_User_Query .

1
FredHead