如何在管理员中从users.php搜索所有用户元


14

“管理员”区域(wp-admin / users.php)中用户列表顶部的搜索表单是受限制的,并且不会搜索所有用户元字段,例如bio,即时Messenger句柄等。我没有能够找到可以添加此内容的插件。

有谁知道我可以创建的插件或函数,从而可以将此搜索扩展到_usermeta数据库中的所有日期-理想情况下,甚至可以由插件或函数创建额外的字段。

Answers:


24

@ user2041,您好

如您所知,您显然需要修改执行的搜索,可以通过修改WP_User_Search用于搜索的类的实例中的值来完成搜索/wp-admin/includes/user.php如果您想研究它,可以找到源代码)。

WP_User_Search对象

print_r()搜索术语TEST且没有任何其他可能影响它的插件时,使用WordPress 3.0.3时,该对象的外观如下:

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文件中使用正在编写的插件,这不仅可以搜索其他字段,还可以搜索用户的描述。该函数修改的query_fromquery_where属性$user_search您需要熟悉SQL才能理解对象。

仔细修改挂钩中的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

启用对Meta使用的专门搜索 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'meta键而不是描述这里有相同的警告)来使用描述

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 2010年

谢谢@MathSmath-知道人们欣赏它是让我前进的动力。:)
MikeSchinkel 2010年

迈克,谢谢您的详尽回答!我将在今天晚些时候将其应用到我的主题中,然后看看它的去向。
约翰·钱德勒

迈克,我们很近,但是..!显然,这使我误入歧途。使用您首先提到的单个功能或使用profile_update的两个功能,就可以搜索并获得正确的结果而言。不幸的是,当我第一次上载users.php(未指定搜索词)时,这些功能使清单混乱。它不会显示所有用户。当我单击“全部”筛选器时,它仅显示两个(四个),其中一个是我,而当我单击“管理员”筛选器时,它没有任何用户-甚至没有我!有任何想法吗?
约翰·钱德勒

更多信息。我编辑了第一个函数,以搜索通过额外用户详细信息插件添加的名为“ company”的字段。当我搜索具有公司名称的用户时,它可以工作。但是,似乎“全部”排序(不进行搜索)仅返回在company字段中具有数据的两个结果,而不返回在company字段中没有数据的用户。
约翰·钱德勒

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_Query自3.1开始弃用了WP_User_Search:http ://codex.wordpress.org/Class_Reference/WP_User_Query 。


1

这是最新版本的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

这就是我为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表联接在一起,并重建WHERE子句以在meta_value列上包括搜索。


1
您在这里提出的建议非常危险!您永远都不要将用户提供的任何信息传递到数据库中。他们可能会删除您的表,劫持您的数据库(将SQL注入作为搜索短语)或仅加密所有数据。做一个"%".like_escape( $_GET['s'] )."%"代替。这同样适用于所有其他用户提供的数据。否则,您的搜索字段将成为数据的开放门户。
kaiser
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.