Yönetici içindeki users.php dosyasındaki tüm kullanıcı metaları nasıl aranır?


14

Yönetici alanında (wp-admin / users.php) listelenen kullanıcıların en üstündeki arama formu sınırlıdır ve bio, anlık mesajlaşma tutamaçları vb. Gibi tüm kullanıcı meta alanlarını aramaz. bunu ekleyebilecek bir eklenti bulabildim.

Herkes bir eklenti veya _usermeta DB tüm tarih için bu aramayı genişletmek yaratabileceğiniz bir işlev farkında - ideal bir eklenti veya işlev tarafından bile ekstra alanlar oluşturmak.

Yanıtlar:


24

Merhaba @ user2041:

Açıkça bildiğiniz gibi, arama WP_User_Searchiçin kullanılan sınıf örneğindeki değerleri değiştirerek yapabileceğiniz aramayı değiştirmeniz gerekir (incelemek isterseniz kaynak kodunu bulabilirsiniz /wp-admin/includes/user.php.)

WP_User_SearchNesne

İşte ne print_r()WordPress 3.0.3 terimi ararken olduğu gibi bu nesne görünüyor " TEST" ve onu etkileyebilecek herhangi bir başka eklenti olmadan:

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_searchKanca

WP_User_SearchNesnenin değerlerini değiştirmek için, nesnenin 'pre_user_search'geçerli örneğini alan kancayı kullanırsınız ; print_r()Yukarıda gösterdiğim değerlere erişmek için o kancadan aradım .

Temanızın functions.phpdosyasına kopyalayabileceğiniz veya yazdığınız bir eklenti için bir PHP dosyasında kullanabileceğiniz aşağıdaki örnek , diğer alanlarda arama yapabilmenin yanı sıra kullanıcının açıklamasında arama yapabilme özelliğini de ekler . İşlev , anlamak için SQL ile rahat olmanız gereken nesnenin query_fromve query_whereözelliklerini değiştirir $user_search.

Kancalarda Dikkatli SQL Değiştirme

İşlevdeki kod, yoursite_pre_user_search()başka hiçbir eklentinin kendisinden önceki query_wheremaddeyi değiştirmediğini varsayar ; başka bir eklenti where yantümcesini değiştirdiğinde değiştirilecek 'WHERE 1=1 AND ('şekilde "WHERE 1=1 AND ({$description_where} OR"çalışmazsa, bu da bozulur. Böyle bir SQL değiştirilirken başka bir eklenti tarafından kırılamayan sağlam bir ek yazmak çok daha zor, ama ne olduğu.

Kancalara SQL Yerleştirirken Önde Gelen ve İzleyen Alanlar Ekleme

Ayrıca WordPress böyle SQL kullanarak zaman lider ve birlikte boşluklarda böyle a sondaki dahil etmek her zaman iyi bir fikir olduğuna dikkat " INNER JOIN {$wpdb->usermeta} ON "önce yer yoktur nerede aşağıdakileri içerebilir aksi takdirde SQL sorgusunun "INNER"kursu başarısız olur,: " FROM wp_postsINNER JOIN {$wpdb->usermeta} ON ".

"{$wpdb->table_name"}Sabit Kodlama Tablo Adları yerine kullanın

Ardından $wpdb, sitenin tablo önekini 'wp_'başka bir şeye değiştirmesi durumunda, tablo adlarına başvurmak için her zaman özellikleri kullandığınızdan emin olun . Bu nedenle, sabit kodlama yerine ( "{$wpdb->users}.ID" tek tırnakla değil, çift tırnaklarla) başvurmak daha iyidir "wp_users.ID".

Sorguyu Yalnızca Arama Terimleri Varsa Sınırla

Son olarak, yalnızca nesnenin search_termözelliğini inceleyerek test edebileceğiniz bir arama terimi olduğunda sorguyu değiştirmek olacaktır WP_User_Search.

İçin yoursite_pre_user_search()işlevi'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);    
  }
}

Her Meta Anahtar / Değer Çiftini Arama SQL gerektirir JOIN

Tabii ki WordPress'in usermeta alanlarında arama yapmasına izin vermemesinin olası nedeni, her birinin JOINsorguya bir SQL eklemesi ve çok fazla birleşime sahip bir sorguya gerçekten yavaş gelmesidir. Gerçekten birçok alanda arama yapmanız gerekiyorsa, o zaman '_search_cache'usermeta'da tüm diğer bilgileri tek bir usermeta alanına toplayan bir alan yaratacağım .

Meta Anahtarlarda Başlıca Alt Çizgiler WordPress'e Görüntülenmemesini Bildirir

Baştaki alt '_search_cache'çizginin WordPress'e bunun dahili bir değer olduğunu ve kullanıcıya gösterilecek bir şey olmadığını söylediğini unutmayın.

'profile_update'Ve 'user_register'Kancalarla bir Arama Önbelleği Oluşturma

Bu nedenle, her ikisini de bağlamanız gerekir 'profile_update've 'user_register'bunlar bir kullanıcıyı kaydetme ve yeni bir kullanıcı kaydetme ile tetiklenir. Bu kancalardaki tüm meta anahtarları ve değerlerini alabilir (ancak serileştirilmiş veya URL kodlu dizileri olan değerleri atlayabilirsiniz) ve ardından '_search_cache'anahtarı kullanarak uzun bir meta değeri olarak depolamak için bunları birleştirebilirsiniz .

'|'Meta'yı Sınırlandırılmış Anahtar / Değer Çiftleri olarak depola

Tüm anahtar isimlerini ve tüm değerlerini yakalamaya ve anahtarları değerlerden ve bu gibi anahtar / değer çiftlerini ayıran dikey çubuklardan ("|") ayıran iki büyük bir dizeye birleştirmeye karar verdim (I bunları sağa kaydırmadan yapabilmeniz için birden çok satıra kaydırdınız):

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

Meta Kullanarak Özel Aramaları Etkinleştirir key:value

Anahtar ve değerleri yaptığımız gibi eklemek rich_editing:true, zengin düzenlemesi olan herkesi bulmak için " " gibi aramalar yapmanıza veya phone:nulltelefon numarası olmayanları bulmak için " " için arama yapmanıza olanak tanır .

Ancak Arama Eserlerine Dikkat Edin

Tabii bu tekniği kullanmak, "iş" araması gibi istenmeyen arama yapaylıkları yaratır ve herkes listelenir. Bu bir sorunsa, bu kadar ayrıntılı bir önbellek kullanmak istemeyebilirsiniz.

yoursite_profile_update()İçin işlev 'profile_update've'user_register'

İşlev için yoursite_profile_update(), yoursite_pre_user_search()yukarıdaki gibi temanızın functions.phpdosyasına kopyalanabilir veya yazdığınız bir eklenti için bir PHP dosyasında kullanabilirsiniz:

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

Tüm İlginç Meta Değerleri Aramak İçin yoursite_pre_user_search()Tek Bir SQL'i Etkinleştiren Güncellenmiş İşlevJOIN

Elbette yoursite_profile_update(), herhangi bir etkiye sahip olmak için , burada sahip olduğumuz açıklama yerine meta anahtarı yoursite_pre_user_search()kullanmak için değiştirmeniz gerekir (yukarıda belirtilenlerle aynı uyarılarla):'_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 Harika, kapsamlı cevap! Bu sitede, stokta olmayan bir soruya iyi araştırılmış bir cevap için birden fazla oy verebilmeyi diliyorum.
MathSmath

Teşekkürler @MathSmath - İnsanların beni takdir etmesini takdir ettiğini öğrenmek. :)
MikeSchinkel

Mike, cevabın için teşekkürler! Bunu bugün daha sonra temamda çalışacağım ve kimin gittiğini göreceğim.
John Chandler

Mike, yakınızdayız, ama ..! Açıkçası bu beni doğru başlangıçtan uzaklaştırıyor. Önce bahsettiğiniz tek bir işlevi veya profile_update kullanmak için iki işlevi kullanarak arama ve uygun sonuçları alma yeteneği açısından çalışıyor. Ne yazık ki, users.php'yi (arama terimi belirtilmedi) ilk kez çektiğimde bu işlevler listeyle uğraşıyor. Tüm kullanıcıları göstermiyor. Tümü filtresini tıklattığımda, yalnızca biri (dörtte biri), biri ben olduğumu gösteriyor ve Yöneticiler filtresini tıkladığımda hiçbir kullanıcı yok - ben bile değil! Herhangi bir fikir?
John Chandler

Biraz daha bilgi. Ekstra kullanıcı detayları eklentisi aracılığıyla eklediğim 'şirket' adlı bir alanı aramak için ilk işlevi düzenledim. Şirket adına sahip bir kullanıcı aradığımda çalışır. Ancak Görünüşe göre, aramaya gerek kalmadan Herkes'e göre sıralama yalnızca şirket alanında veri bulunan iki sonucu döndürüyor ve şirket alanında veri içermeyen kullanıcıları döndürmüyor.
John Chandler

5

MikeSchinkel'in yaklaşımını ve yukarıdaki kapsamlı açıklamayı gerçekten takdir ettim. Bu süper yardımcı oldu. Pre_user_search kullanımdan kaldırıldığından ve aslında 3.2'de çalışmadığından benim için çalışamadım. Ben sadece pre_user_query ile geçiş denedim ama o da işe yaramadı. Mesele şu ki, $ user_search-> search_term artık çalışmıyor, bu yüzden sadece $ _GET ['s'] kullandım. Biraz hack yaptım ve bunu 3.2'de çalıştırabildim. Ayarlamanız gereken tek şey, aranabilir meta veri dizinizdir.

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

Umarım bu birine yardımcı olur.


Bunların herhangi biri ile yakın zamanda deneyimleri olan var mı? Şahsen, en son olanlar da dahil olmak üzere bu kod parçalarından herhangi birini çalıştıramıyorum. Başka seçenekler denedim, ancak sonuç sayfalandırma ile ilgili sorunlar buldum .
Robert Andrews


1

İşte wordpress'in en yeni sürümüne bir çözüm.

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

Bu, tüm kullanıcı meta verilerine joker arama ekleyen WordPress 4.7.1 için bulduğum şeydir.


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

Temel olarak, kullanıcı kimliğindeki users ve user_meta tablolarına katılıyor ve meta_değeri sütununda aramayı içerecek şekilde WHERE yan tümcesini yeniden oluşturuyoruz.


1
Burada önerdiğiniz şey son derece tehlikelidir ! Sen gerektiğini , şimdiye kadar hiç veritabanına bir kullanıcı tarafından sağlanmaktadır ne olursa olsun geçmektedir. Tablolarınızı bırakabilir, veritabanınızı ele geçirebilir (SQL enjeksiyonunu arama ifadesi olarak görebilir) veya tüm verilerinizi şifreleyebilirler. Bunun "%".like_escape( $_GET['s'] )."%"yerine yapın. Aynı şey, kullanıcı tarafından sağlanan diğer tüm veriler için de geçerlidir . Aksi takdirde arama alanınız verilerinize açık bir ağ geçidi haline gelir.
Kaiser
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.