adminでusers.phpからすべてのユーザーメタを検索する方法


14

管理エリア(wp-admin / users.php)のユーザーリストの上部にある検索フォームは制限されており、バイオ、インスタントメッセンジャーハンドルなどのユーザーメタフィールドのすべてを検索しません。これを追加できるプラグインを見つけることができました。

_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にフィールドを作成し、他のすべての情報を1つのusermetaフィールドに収集して、すべてを検索するために1つの結合のみを必要とします。

メタキーの主要なアンダースコアはWordPressに表示しないよう指示します

先頭のアンダースコア'_search_cache'は、これが内部値であり、ユーザーに表示するものではないことをWordPress に伝えることに注意してください。

'profile_update''user_register'フックで検索キャッシュを作成する

あなたは両方をフックする必要がありますので、'profile_update'そして'user_register'それは、ユーザを保存して、それぞれ、新規ユーザを登録するにはトリガーされます。これらのフック内のすべてのメタキーとその値を取得し(ただし、シリアル化された値またはURLエンコードされた配列を持つものは省略します)'_search_cache'キーを使用して1つの長いメタ値として格納するためにそれらを連結します。

メタを'|'区切りキーと値のペアとして保存

すべてのキー名とすべての値を取得し、これらをキーと値を区切るコロン( ":")とこのようなキーと値のペアを区切る垂直バー( "|")で1つの大きな文字列に連結することにしました(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'

functionの場合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すばらしい、徹底的な答え!これは、このサイトで何度も行われているものの1つです。ここでは、在庫のない質問に対するよく研究された回答に対して、複数の賛成票を配ることができます。
MathSmath

@MathSmathに感謝-人々がそれを高く評価していることを知ることが、私を前進させている。:)
MikeSchinkel

マイク、徹底的な答えをありがとう!今日はこれをテーマに組み込んで、誰が行くのか見てみましょう。
ジョンチャンドラー

マイク、私たちは近いが、..!明らかにこれは私が正しいスタートを切っていることを示しています。最初に言及した単一の関数、またはprofile_updateを利用する2つの関数のいずれかを使用することは、適切な結果を検索して取得する機能の観点から機能します。残念ながら、これらの関数は、users.php(検索語が指定されていない)を最初にプルアップしたときにリストを台無しにします。すべてのユーザーを表示しているわけではありません。[すべて]フィルターをクリックすると、2つ(4つのうち)のみが表示され、そのうちの1つは私です。[管理者]フィルターをクリックすると、ユーザーは表示されません。何か案は?
ジョンチャンドラー

もう少し情報。最初の関数を編集して、追加のユーザー詳細プラグインを介して追加した「company」というフィールドを検索しました。会社名を持つユーザーを検索すると機能します。ただし、検索なしですべてでソートすると、会社フィールドにデータがある2つの結果のみが返され、会社フィールドにデータがないユーザーは返されないようです。
ジョンチャンドラー

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

これが誰かを助けることを願っています。


このいずれかで最近の経験はありますか?個人的には、最新のコードを含め、これらのコードの一部を機能させることはできません。他のいくつかのオプションを試しましたが、結果のページネーションに問題が見つかりました。
ロバートアンドリュース

1

参考までに、このトピック(ユーザーパネルの検索クエリを調整する方法)で検索し、この優れたページを見つける人々のために、WP_User_Searchは3.1:http ://codex.wordpress.org/Class_Reference/WP_User_Queryの時点でWP_User_Queryによって非推奨になりました。


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でユーザーテーブルとuser_metaテーブルを結合し、WHERE句を再構築して、meta_value列の検索を含めるだけです。


1
ここで提案していることは非常に危険です!ユーザーから提供されたものをDBに渡さないでください。テーブルを削除したり、データベースをハイジャックしたり(検索フレーズとしてのSQLインジェクションを参照)、あるいは単にすべてのデータを暗号化したりできます。やる"%".like_escape( $_GET['s'] )."%"代わりに。同じことが、他のすべてのユーザー提供データにも当てはまります。それ以外の場合、検索フィールドはデータへのオープンゲートウェイになります。
カイザー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.