count_users()
云策文档标注
概述
count_users() 函数用于统计站点中每个用户角色的用户数量,返回包含总用户数和按角色分类计数的数组。支持两种计算策略:'time'(CPU 密集型)和 'memory'(内存密集型),并可通过过滤器进行自定义。
关键要点
- 函数返回一个数组,包含 total_users(总用户数)和 avail_roles(按角色键值对计数的数组)。
- 接受两个可选参数:$strategy(计算策略,默认为 'time')和 $site_id(站点 ID,默认为当前站点)。
- 使用 'time' 策略时,通过复杂 SQL 查询高效处理大量用户(约 10^7),但假设角色名称唯一且无重复能力元值。
- 使用 'memory' 策略时,通过内存操作处理较少用户(约 10^5),但可能存在 WP Bug #12257 相关限制。
- 提供 pre_count_users 过滤器,允许在查询前自定义返回结果。
- 支持多站点环境,通过 $site_id 参数指定要统计的站点。
代码示例
$result = count_users();
echo 'There are ', $result['total_users'], ' total users';
foreach( $result['avail_roles'] as $role => $count )
echo ', ', $count, ' are ', $role, 's';
echo '.';注意事项
- 函数假设用户角色名称是唯一短语,且无重复或孤立的能力元值,与 WP_User_Query::prepare_query() 相同。
- 在 'time' 策略下,如果涉及多站点且非当前站点,会临时切换博客以获取角色列表。
- 返回的 avail_roles 数组不包含计数为 0 的角色,适合在 foreach 循环中使用。
- 自 4.9.0 版本起添加 $site_id 参数以支持多站点;4.4.0 版本起在 none 元素中包含无角色用户数。
原文内容
Counts number of users who have each of the user roles.
Description
Assumes there are neither duplicated nor orphaned capabilities meta_values.
Assumes role names are unique phrases. Same assumption made by WP_User_Query::prepare_query() Using $strategy = ‘time’ this is CPU-intensive and should handle around 10^7 users.
Using $strategy = ‘memory’ this is memory-intensive and should handle around 10^5 users, but see WP Bug #12257.
Parameters
$strategystringoptional-
The computational strategy to use when counting the users.
Accepts either'time'or'memory'. Default'time'. $site_idint|nulloptional-
The site ID to count users for. Defaults to the current site.
Default:
null
Source
function count_users( $strategy = 'time', $site_id = null ) {
global $wpdb;
// Initialize.
if ( ! $site_id ) {
$site_id = get_current_blog_id();
}
/**
* Filters the user count before queries are run.
*
* Return a non-null value to cause count_users() to return early.
*
* @since 5.1.0
*
* @param null|array $result The value to return instead. Default null to continue with the query.
* @param string $strategy Optional. The computational strategy to use when counting the users.
* Accepts either 'time' or 'memory'. Default 'time'.
* @param int $site_id The site ID to count users for.
*/
$pre = apply_filters( 'pre_count_users', null, $strategy, $site_id );
if ( null !== $pre ) {
return $pre;
}
$blog_prefix = $wpdb->get_blog_prefix( $site_id );
$result = array();
if ( 'time' === $strategy ) {
if ( is_multisite() && get_current_blog_id() !== $site_id ) {
switch_to_blog( $site_id );
$avail_roles = wp_roles()->get_names();
restore_current_blog();
} else {
$avail_roles = wp_roles()->get_names();
}
// Build a CPU-intensive query that will return concise information.
$select_count = array();
foreach ( $avail_roles as $this_role => $name ) {
$select_count[] = $wpdb->prepare( 'COUNT(NULLIF(`meta_value` LIKE %s, false))', '%' . $wpdb->esc_like( '"' . $this_role . '"' ) . '%' );
}
$select_count[] = "COUNT(NULLIF(`meta_value` = 'a:0:{}', false))";
$select_count = implode( ', ', $select_count );
// Add the meta_value index to the selection list, then run the query.
$row = $wpdb->get_row(
"
SELECT {$select_count}, COUNT(*)
FROM {$wpdb->usermeta}
INNER JOIN {$wpdb->users} ON user_id = ID
WHERE meta_key = '{$blog_prefix}capabilities'
",
ARRAY_N
);
// Run the previous loop again to associate results with role names.
$col = 0;
$role_counts = array();
foreach ( $avail_roles as $this_role => $name ) {
$count = (int) $row[ $col++ ];
if ( $count > 0 ) {
$role_counts[ $this_role ] = $count;
}
}
$role_counts['none'] = (int) $row[ $col++ ];
// Get the meta_value index from the end of the result set.
$total_users = (int) $row[ $col ];
$result['total_users'] = $total_users;
$result['avail_roles'] =& $role_counts;
} else {
$avail_roles = array(
'none' => 0,
);
$users_of_blog = $wpdb->get_col(
"
SELECT meta_value
FROM {$wpdb->usermeta}
INNER JOIN {$wpdb->users} ON user_id = ID
WHERE meta_key = '{$blog_prefix}capabilities'
"
);
foreach ( $users_of_blog as $caps_meta ) {
$b_roles = maybe_unserialize( $caps_meta );
if ( ! is_array( $b_roles ) ) {
continue;
}
if ( empty( $b_roles ) ) {
++$avail_roles['none'];
}
foreach ( $b_roles as $b_role => $val ) {
if ( isset( $avail_roles[ $b_role ] ) ) {
++$avail_roles[ $b_role ];
} else {
$avail_roles[ $b_role ] = 1;
}
}
}
$result['total_users'] = count( $users_of_blog );
$result['avail_roles'] =& $avail_roles;
}
return $result;
}
Hooks
- apply_filters( ‘pre_count_users’, null|array $result, string $strategy, int $site_id )
-
Filters the user count before queries are run.
Skip to note 2 content
Codex
Basic Example
The call to count_users returns the number of users with each role. It will not return any roles having count == 0, so the results are intended to be used in foreach loops.
$result = count_users(); echo 'There are ', $result['total_users'], ' total users'; foreach( $result['avail_roles'] as $role => $count ) echo ', ', $count, ' are ', $role, 's'; echo '.';Output example is: