Come cercare tutti i meta utente da users.php nell'amministratore


14

Il modulo di ricerca nella parte superiore dell'elenco degli utenti nell'area di amministrazione (wp-admin / users.php) è limitato e non cerca tutti i meta campi dell'utente, come bio, handle di messaggistica istantanea, ecc. stato in grado di trovare un plug-in che può aggiungere questo.

Qualcuno è a conoscenza di un plugin o di una funzione che potrei creare che potrebbe espandere questa ricerca per tutte le date nel DB _usermeta - idealmente anche campi extra creati da un plugin o una funzione.

Risposte:


24

Ciao @ user2041:

Chiaramente, come sapete, è necessario modificare la ricerca eseguita, che è possibile fare modificando i valori nell'istanza della WP_User_Searchclasse utilizzata per la ricerca (è possibile trovare il codice sorgente /wp-admin/includes/user.phpse si desidera studiarlo.)

L' WP_User_Searchoggetto

Ecco print_r()come appare uno di quegli oggetti con WordPress 3.0.3 quando si cerca il termine " TEST" e senza altri plugin che potrebbero influenzarlo:

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

The pre_user_searchHook

Per modificare i valori WP_User_Searchdell'oggetto utilizzerai l' 'pre_user_search'hook che riceve l'istanza corrente dell'oggetto; Ho chiamato print_r()da quel gancio per ottenere l'accesso ai suoi valori che ho visualizzato sopra.

Il seguente esempio che puoi copiare nel functions.phpfile del tuo tema o che puoi utilizzare in un file PHP per un plugin che stai scrivendo aggiunge la possibilità di cercare nella descrizione dell'utente oltre a poter cercare negli altri campi. La funzione modifica le query_frome le query_whereproprietà $user_searchdell'oggetto che devi comprendere con SQL per capire.

Attenta modifica di SQL in Hooks

Il codice nella yoursite_pre_user_search()funzione presuppone che nessun altro plugin abbia modificato la query_whereclausola prima di essa; se un altro plugin ha modificato la clausola where in modo che la sostituzione 'WHERE 1=1 AND ('con "WHERE 1=1 AND ({$description_where} OR"non funzioni più, anche questo si interromperà. È molto più difficile scrivere un'aggiunta solida che non può essere interrotta da un altro plugin quando si modifica SQL in questo modo, ma è quello che è.

Aggiungi spazi iniziali e finali quando inserisci SQL negli hook

Si noti inoltre che quando si utilizza SQL come questo in WordPress è sempre una buona idea includere spazi iniziali e finali, quali una con " INNER JOIN {$wpdb->usermeta} ON "altrimenti la query SQL potrebbe contenere il seguente dove non c'è spazio prima "INNER", che naturalmente non riuscire: " FROM wp_postsINNER JOIN {$wpdb->usermeta} ON ".

Utilizzare al "{$wpdb->table_name"}posto dei nomi tabella hardcoding

Quindi assicurati di utilizzare sempre le $wpdbproprietà per fare riferimento ai nomi delle tabelle nel caso in cui il sito abbia modificato il prefisso della tabella da 'wp_'qualcos'altro. Quindi è meglio fare riferimento "{$wpdb->users}.ID" (con virgolette doppie, non singole) invece di hardcoding "wp_users.ID".

Limitare la query a Solo quando esistono i termini di ricerca

Infine, modificare la query solo quando esiste un termine di ricerca che è possibile verificare controllando la search_termproprietà WP_User_Searchdell'oggetto.

La yoursite_pre_user_search()funzione per'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 ricerca di ogni coppia Meta-valore chiave richiede un SQL JOIN

Naturalmente il probabile motivo per cui WordPress non ti consente di cercare nei campi usermeta è che ognuno aggiunge un SQL JOINalla query e una query con troppi join può essere effettivamente lenta. Se hai davvero bisogno di cercare in molti campi, '_search_cache'creerei un campo in usermeta che raccoglie tutte le altre informazioni in un campo usermeta per richiedere un solo join per cercare tutto.

I caratteri di sottolineatura principali in Meta Keys indicano a WordPress di non visualizzare

Si noti che il carattere di sottolineatura iniziale in '_search_cache'dice a WordPress che questo è un valore interno e non qualcosa da mostrare all'utente.

Creare una cache di ricerca con i hook 'profile_update'e'user_register'

Quindi dovrai agganciare entrambi 'profile_update'e 'user_register'che sono attivati ​​sul salvataggio di un utente e sulla registrazione di un nuovo utente, rispettivamente. Puoi prendere tutte le meta-chiavi e i loro valori in quegli hook (ma omettere quelle con valori che sono array serializzati o con codifica URL) e quindi concatenarle per archiviarle come un lungo meta-valore usando la '_search_cache'chiave.

Memorizza Meta come '|'coppie chiave-valore delimitate

Ho deciso di prendere tutti i nomi delle chiavi e tutti i loro valori e concatenarli in un'unica grande stringa con due punti (":") che separano le chiavi dai valori e dalle barre verticali ("|") che separano le coppie chiave-valore in questo modo (I li hai avvolti su più righe in modo da poterli scorrere senza scorrere verso destra):

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

Abilita ricerche specializzate su Meta Using key:value

L'aggiunta della chiave e dei valori, come abbiamo fatto, ti consente di effettuare ricerche come " rich_editing:true" per trovare tutti coloro che hanno modifiche avanzate o cercare " phone:null" per trovare quelle senza numero di telefono.

Ma attenzione agli artefatti di ricerca

Naturalmente l'uso di questa tecnica crea artefatti di ricerca potenzialmente indesiderati come la ricerca di "affari" e tutti saranno elencati. Se questo è un problema, potresti non voler utilizzare una cache così elaborata.

La yoursite_profile_update()funzione per 'profile_update'e'user_register'

Per funzione yoursite_profile_update(), come yoursite_pre_user_search()sopra può essere copiato nel functions.phpfile del tuo tema oppure puoi usarlo in un file PHP per un plugin che stai scrivendo:

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()Funzione aggiornata che abilita un singolo SQL JOINper la ricerca di tutti i meta valori interessanti

Ovviamente per yoursite_profile_update()avere qualche effetto dovrai modificare yoursite_pre_user_search()per usare la '_search_cache'meta chiave invece della descrizione, che abbiamo qui (con gli stessi avvertimenti di cui sopra):

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 Ottima risposta completa! Questa è una delle tante volte su questo sito in cui vorrei poter dare più voti per una risposta così ben studiata a una domanda non di magazzino.
MathSmath,

Grazie @MathSmath - Imparare che la gente lo apprezza è ciò che mi fa andare avanti. :)
MikeSchinkel,

Mike, grazie per la risposta esaustiva! Lavorerò sul mio tema più tardi oggi e vedrò chi va.
John Chandler,

Mike, siamo vicini, ma ..! Chiaramente questo mi sta facendo partire nel modo giusto. Utilizzando la singola funzione menzionata per prima, oppure le due funzioni per utilizzare il profilo_update funzionano in termini di capacità di ricerca e ottenere i risultati corretti. Sfortunatamente, queste funzioni sono in disordine con l'elenco quando ho prima tirato su utenti.php (che non è stato specificato alcun termine di ricerca). Non mostra tutti gli utenti. Quando faccio clic sul filtro Tutti, vengono visualizzati solo due (su quattro), uno dei quali sono io, e quando faccio clic sul filtro Amministratori, non ci sono utenti, nemmeno io! Qualche idea?
John Chandler,

Qualche informazione in più. Ho modificato la prima funzione per cercare un campo chiamato "azienda" che ho aggiunto tramite il plug-in dei dettagli utente aggiuntivo. Funziona quando cerco un utente con un nome di società. Tuttavia, sembra che l'ordinamento per Tutti, senza ricerca, stia solo restituendo i due risultati che hanno dati nel campo dell'azienda e non restituendo gli utenti che non hanno dati nel campo dell'azienda.
John Chandler,

5

Ho davvero apprezzato l'approccio di MikeSchinkel e la spiegazione approfondita sopra. Questo è stato di grande aiuto. Non sono riuscito a farlo funzionare per me poiché pre_user_search è stato deprecato e in realtà non funziona in 3.2. Ho provato a cambiarlo con pre_user_query ma non ha funzionato neanche. Il fatto è che sembra che $ user_search-> search_term non funzioni più, quindi ho appena usato $ _GET ['s']. Ho eliminato alcuni hack e sono riuscito a farlo funzionare in 3.2. L'unica cosa che devi impostare è il tuo array di metadati ricercabili.

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

Spero che questo aiuti qualcuno.


Qualcuno ha qualche esperienza recente con questo? Personalmente, non riesco a far funzionare nessuno di questi bit di codice, compresi quelli più recenti. Ho provato alcune altre opzioni, ma ho riscontrato problemi con l'impaginazione dei risultati .
Robert Andrews,


1

Ecco una soluzione alla versione più recente di 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

Questo è ciò che mi è venuto in mente per WordPress 4.7.1 che aggiunge la ricerca con caratteri jolly a tutti i metadati dell'utente.


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

Fondamentalmente stiamo solo unendo gli utenti e le tabelle user_meta sull'ID utente e ricostruendo la clausola WHERE per includere la ricerca nella colonna meta_value.


1
Quello che stai suggerendo qui è altamente pericoloso ! Non dovresti mai, mai passare tutto ciò che viene fornito da un utente nel DB. Potrebbero eliminare le tue tabelle, dirottare il tuo database - vedi iniezione SQL come frase di ricerca - o semplicemente crittografare tutti i tuoi dati. Fai un "%".like_escape( $_GET['s'] )."%"invece. Lo stesso vale per tutti gli altri dati forniti dall'utente . Altrimenti il ​​tuo campo di ricerca diventa un gateway aperto ai tuoi dati.
Kaiser
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.