관리자의 users.php에서 모든 사용자 메타를 검색하는 방법


14

관리 영역 (wp-admin / users.php)의 사용자 목록 상단에있는 검색 양식은 제한되어 있으며 bio, 인스턴트 메신저 핸들 등과 같은 모든 사용자 메타 필드를 검색하지는 않습니다. 이것을 추가 할 수있는 플러그인을 찾을 수있었습니다.

누구나 _usermeta DB의 모든 날짜에 대해이 검색을 확장 할 수있는 플러그인이나 함수를 알고 있습니까? 플러그인이나 함수로 만든 추가 필드도 이상적입니다.

답변:


24

안녕하세요 @ user2041 :

검색에 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 파일에서 사용할 수있는 다음 예 는 다른 필드를 검색 할 수있을뿐만 아니라 사용자 설명검색 하는 기능을 추가합니다. 이 함수는 이해하기 위해 SQL에 익숙해 져야 하는 오브젝트 query_fromquery_where특성을 수정합니다 $user_search.

후크에서 조심스럽게 SQL 수정

yoursite_pre_user_search()함수 의 코드는 다른 플러그인이 query_where절 을 수정하지 않았다고 가정 합니다. 다른 플러그인이 where 절을 수정 한 경우 교체하도록 'WHERE 1=1 AND ('하여 "WHERE 1=1 AND ({$description_where} OR"더 이상 작품은 다음이도 중단됩니다. 이와 같이 SQL을 수정할 때 다른 플러그인으로 인해 깨지지 않는 강력한 추가 기능을 작성하는 것이 훨씬 어렵지만 이것이 바로 그 기능입니다.

후크에 SQL을 삽입 할 때 선행 및 후행 공백 추가

또한 WordPress에서 이와 같은 SQL을 사용할 때 항상 앞뒤 공백을 포함하는 것이 좋습니다. " 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 필드를 검색 할 수없는 이유는 각각 JOIN쿼리에 SQL 을 추가하고 조인이 너무 많은 쿼리는 실제로 느릴 수 있기 때문입니다. 많은 필드를 실제로 검색 해야하는 경우 '_search_cache'usermeta에서 모든 다른 정보를 하나의 usermeta 필드로 수집하여 모든 검색을 위해 하나의 조인 만 필요로하는 필드를 만듭니다.

메타 키의 밑줄은 WordPress에 표시하지 않도록 지시합니다.

밑줄을 선행 '_search_cache'하면 WordPress에 이것이 내부 값이며 사용자에게 표시 할 것이 아니라는 것을 알려줍니다.

'profile_update''user_register'후크를 사용하여 검색 캐시 만들기

따라서 사용자를 저장하고 새 사용자를 등록 할 때 트리거되는 'profile_update'것과 'user_register'이를 모두 연결해야합니다 . 해당 후크에서 모든 메타 키와 해당 값을 가져 와서 ( 직렬화 된 값 또는 URL 인코딩 배열이있는 값은 생략)'_search_cache' 키를 사용하여 하나의 긴 메타 값으로 저장하도록 연결할 수 있습니다 .

'|'구분 된 키-값 쌍 으로 메타 저장

모든 키 이름과 모든 값을 가져 와서 콜론 ( ":")을 사용하여 키를 값과 세로 막대 ( "|")에서 분리하고 키-값 쌍을 다음과 같이 분리하여 하나의 큰 문자열로 연결하기로 결정했습니다 (I 오른쪽으로 스크롤하지 않고 여러 줄로 줄 바꿈했습니다.)

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

@MikeSchinkel 훌륭하고 철저한 답변! 이것은이 사이트에서 여러 번 중 하나이며 비 재고 질문에 대한 잘 연구 된 답변에 대해 여러 개의 투표를 줄 수 있기를 바랍니다.
MathSmath

@MathSmath에게 감사드립니다-사람들이 그것을 이해한다는 것을 배우는 것이 저를 계속합니다. :)
MikeSchinkel

마이크, 철저한 답변 감사합니다! 오늘 나중에이 주제를 주제로 다루고 그것이 누구인지 살펴 보겠습니다.
John Chandler

마이크, 우리는 가까이 있지만 ..! 분명히 이것은 올바른 시작에서 벗어나게합니다. 먼저 언급 한 단일 함수 또는 profile_update를 활용하는 두 가지 함수를 사용하여 검색하고 적절한 결과를 얻을 수 있습니다. 불행히도이 함수는 users.php (검색어가 지정되지 않음)를 처음 가져올 때 목록을 망칩니다. 모든 사용자를 표시하지는 않습니다. All 필터를 클릭하면 2 개 (4 개 중 1 개) 만 표시되며 그 중 하나는 나입니다. Administrators 필터를 클릭하면 사용자는 물론 저도 아닙니다! 어떤 아이디어?
John Chandler

조금 더 정보. 추가 사용자 세부 정보 플러그인을 통해 추가 한 'company'라는 필드를 검색하기 위해 첫 번째 기능을 편집했습니다. 회사 이름을 가진 사용자를 검색하면 작동합니다. 그러나 검색하지 않고 모두를 기준으로 정렬하면 회사 필드에 데이터가있는 두 개의 결과 만 반환하고 회사 필드에 데이터가없는 사용자는 반환하지 않는 것으로 보입니다.
John Chandler

5

MikeSchinkel의 접근 방식과 위의 철저한 설명에 정말 감사했습니다. 이것은 매우 도움이되었습니다. 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);    
}

이것이 누군가를 돕기를 바랍니다.


누구든지 이것에 대해 최근에 경험이 있습니까? 개인적으로 최신 코드를 포함하여 이러한 코드를 작동시킬 수 없습니다. 다른 옵션을 시도했지만 결과 페이지 매김에 문제가 있습니다.
Robert Andrews


1

다음은 최신 버전의 워드 프레스에 대한 솔루션입니다.

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

이것은 모든 사용자 메타 데이터에 와일드 카드 검색을 추가하는 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;
}

기본적으로 우리는 사용자 ID에서 users 및 user_meta 테이블을 조인하고 meta_value 열에 대한 검색을 포함하도록 WHERE 절을 다시 작성합니다.


1
당신이 여기에서 제안하는 것은 매우 위험합니다 ! 사용자 가 제공 한 모든 것을 DB로 전달 해서는 안됩니다 . 테이블을 삭제하거나 데이터베이스를 가로 채거나 (SQL 삽입을 검색 구문으로 참조) 모든 데이터를 암호화 할 수 있습니다. 를 수행 "%".like_escape( $_GET['s'] )."%"하는 대신. 다른 모든 사용자 제공 데이터도 마찬가지 입니다. 그렇지 않으면 검색 필드가 데이터의 개방형 게이트웨이가됩니다.
카이저
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.