问题描述

在管理区域 (wp-admin /users.php) 中列出的用户顶部的搜索表单受到限制,并且不搜索所有用户元字段,例如生物,即时消息手柄等。我还没有找到一个可以添加的插件。

有人知道一个插件或一个可以创建的功能,可以扩展这个搜索在_usermeta 数据库中的所有日期 – 理想情况下甚至由插件或函数创建的额外字段。

最佳解决方案

嗨 @ user2041:

很明显,如你所知,您需要通过修改用于搜索的 WP_User_Search 类的实例中的值来修改执行的搜索 (您可以在/wp-admin/includes/user.php 找到源代码,如果您想学习的话) 。

WP_User_Search 对象

以下是搜索 「TEST」 并且没有任何其他可能影响到的插件时,该对象的 print_r()与 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 文件中使用您正在编写的插件,除了可以在其他字段上搜索之外,还可以搜索用户描述。该功能修改了 $user_search 对象的 query_fromquery_where 属性,您需要使用 SQL 才能理解。

仔细修改钩子中的 SQL

yoursite_pre_user_search()函数中的代码假定没有其他插件在它之前修改了 query_where 子句; 如果另一个插件已经修改了 where 子句,以便用"WHERE 1=1 AND ({$description_where} OR"替换'WHERE 1=1 AND ('不再工作,那么这也将中断。编写一个强大的补丁比在这样修改 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"

仅当搜索条件存在时才将查询限制为

最后只能通过检查 WP_User_Search 对象的 search_term 属性来检查可以测试的搜索项时修改查询。

'pre_user_search'yoursite_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);
  }
}

搜索每个元 Key-Value 对需要一个 SQL JOIN

当然,WordPress 不允许您在 usermeta 字段上搜索的可能原因是每个人都向查询添加了一个 SQL JOIN,并且具有太多连接的查询可能会很慢。如果您真的需要搜索许多字段,那么我将在 usermeta 中创建一个'_search_cache'字段,将所有其他信息收集到一个 usermeta 字段中,以便只需要一个联接即可搜索。

Meta Keys 中的主要下划线告诉 WordPress 不显示

请注意,'_search_cache'的领先下划线告诉 WordPress 这是一个内部值,而不是向用户显示的东西。

使用'profile_update''user_register'钩子创建搜索缓存

因此,您需要分别在保存用户和注册新用户时触发的'profile_update''user_register'。您可以抓住这些钩子中的所有元键及其值 (但忽略具有串行化或 URL 编码数组的值),然后连接它们以使用'_search_cache'键存储为一个长元值。

存储元数据为'|'定界 Key-Value 对

我决定抓住所有的关键名字和所有的值,并将它们与冒号 (“:”) 连接成一个大字符串 (“:”),将键与值和垂直条 (“|”) 分开,这样分离 key-value 对 (我将它们包装成多个行,所以你可以他们没有滚动到右边):

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 启用 Meta 专业搜索

按照我们所提供的关键字和值可以让您进行诸如 「rich_editing:true」 的搜索,以查找具有丰富编辑的所有人,或者搜索 「phone:null」 以找到没有电话号码的用户。

但请注意搜索人工制品

当然,使用这种技术可能会产生不必要的搜索工件,例如搜索”business”,并且每个人都将被列出。如果这是一个问题,那么你可能不想使用这样一个精心设计的缓存。

'profile_update''user_register'yoursite_profile_update()功能

对于函数 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 的方法和上面的彻底解释。这是 super-helpful 。我不能让它为我工作,因为 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);
}

希望这有助于某人。

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。