Olá @ user2041:
Claramente, como você sabe, precisa modificar a pesquisa executada, o que pode ser feito modificando os valores na instância da WP_User_Search
classe usada para a pesquisa (você pode encontrar o código-fonte /wp-admin/includes/user.php
se quiser estudá-lo.)
O WP_User_Search
Objeto
Veja como é print_r()
esse objeto no WordPress 3.0.3 ao pesquisar o termo " TEST
" e sem outros plugins que possam afetá-lo:
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_search
Hook
Para modificar os valores do WP_User_Search
objeto, você usará o 'pre_user_search'
gancho que recebe a instância atual do objeto; Liguei print_r()
de dentro desse gancho para ter acesso aos seus valores que exibi acima.
O exemplo a seguir, que você pode copiar no functions.php
arquivo do seu tema ou em um arquivo PHP para um plug-in que você está escrevendo, adiciona a capacidade de pesquisar na descrição do usuário, além de poder pesquisar nos outros campos. A função modifica os query_from
e as query_where
propriedades do $user_search
objeto que você precisa para ser confortável com o SQL de entender.
Modificação cuidadosa de SQL em ganchos
O código na yoursite_pre_user_search()
função assume que nenhum outro plugin modificou a query_where
cláusula anterior a ele; se outro plug-in tiver modificado a cláusula where, de modo que a substituição 'WHERE 1=1 AND ('
por "WHERE 1=1 AND ({$description_where} OR"
não funcione mais, isso também será interrompido. É muito mais difícil escrever uma adição robusta que não possa ser quebrada por outro plug-in ao modificar o SQL como este, mas é o que é.
Adicionar espaços à esquerda e à direita ao inserir SQL em ganchos
Observe também que quando se utiliza SQL como esta em WordPress é sempre uma boa idéia de incluir esquerda e à direita espaços, um com " INNER JOIN {$wpdb->usermeta} ON "
outra forma sua consulta SQL pode conter o seguinte, onde não há espaço antes "INNER"
, o que, naturalmente, falhar: " FROM wp_postsINNER JOIN {$wpdb->usermeta} ON "
.
Use em "{$wpdb->table_name"}
vez de codificar nomes de tabela
Em seguida, certifique-se de sempre usar as $wpdb
propriedades para fazer referência aos nomes das tabelas, caso o site altere o prefixo da tabela de 'wp_'
para outra coisa. Portanto, é melhor consultar "{$wpdb->users}.ID"
(com aspas duplas, não aspas simples) em vez de codificar "wp_users.ID"
.
Limitar a consulta apenas quando existirem termos de pesquisa
Por fim, modifique a consulta apenas quando houver um termo de pesquisa que você possa testar inspecionando a search_term
propriedade do WP_User_Search
objeto.
A yoursite_pre_user_search()
função para'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);
}
}
Pesquisando cada par meta-valor-chave requer um SQL JOIN
É claro que o provável motivo pelo qual o WordPress não permite pesquisar campos de meta-usuário é que cada um adiciona um SQL JOIN
à consulta e uma consulta com muitas junções pode ser lenta. Se você realmente precisar pesquisar em muitos campos, eu criaria um '_search_cache'
campo no usermeta que coleta todas as outras informações em um campo do usermeta para exigir apenas uma associação para pesquisar tudo.
Os sublinhados principais em Meta Keys dizem ao WordPress para não ser exibido
Observe que o sublinhado à esquerda '_search_cache'
informa ao WordPress que esse é um valor interno e não algo que deve ser exibido ao usuário.
Criar um cache de pesquisa com os ganchos 'profile_update'
e'user_register'
Portanto, você precisará conectar ambos 'profile_update'
e 'user_register'
que são acionados para salvar um usuário e registrar um novo usuário, respectivamente. Você pode pegar todas as meta chaves e seus valores nesses ganchos (mas omitir aqueles com valores serializados ou matrizes codificados por URL) e concatená-los para armazenar como um meta valor longo usando a '_search_cache'
chave
Armazenar meta como '|'
pares de valor-chave delimitado
Decidi pegar todos os nomes de chave e todos os seus valores e concatená-los em uma grande sequência com dois pontos (":") separando as chaves dos valores e barras verticais ("|") que separam os pares de valores-chave como este (I os agrupamos em várias linhas para que você possa usá-los sem rolar para a direita):
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
Permite pesquisas especializadas no Meta usando key:value
Adicionar a chave e os valores, como fizemos, permite fazer pesquisas como " rich_editing:true
" para encontrar todos os que têm edição rica ou procurar " phone:null
" para encontrar aqueles sem número de telefone.
Mas cuidado com os artefatos de pesquisa
É claro que o uso dessa técnica cria artefatos de pesquisa possivelmente indesejados, como pesquisa por "negócios", e todos serão listados. Se isso for um problema, talvez você não queira usar um cache tão elaborado.
A yoursite_profile_update()
função para 'profile_update'
e'user_register'
Para a função yoursite_profile_update()
, como yoursite_pre_user_search()
acima, pode ser copiado para o functions.php
arquivo do seu tema ou você pode usar em um arquivo PHP o plugin que está escrevendo:
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()
Função atualizada, habilitando um único SQL JOIN
para pesquisar todos os meta-valores interessantes
Obviamente, para yoursite_profile_update()
ter algum efeito, você precisará modificar yoursite_pre_user_search()
para usar a '_search_cache'
meta-chave em vez da descrição, que temos aqui (com as mesmas ressalvas mencionadas acima):
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);
}
}