count_users( string $strategy = 'time', int|null $site_id = null )

Count number of users who have each of the user roles.


Description 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 Parameters

$strategy

(string) (Optional) The computational strategy to use when counting the users. Accepts either 'time' or 'memory'.

Default value: 'time'

$site_id

(int|null) (Optional) The site ID to count users for. Defaults to the current site.

Default value: null


Top ↑

Return Return

(array) Includes a grand total and an array of counts indexed by role strings.


Top ↑

Source Source

File: wp-includes/user.php

function count_users( $strategy = 'time', $site_id = null ) {
	global $wpdb;

	// Initialize
	if ( ! $site_id ) {
		$site_id = get_current_blog_id();
	}

	/**
	 * Filter 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|string $result   Default null.
	 * @param string      $strategy Optional. The computational strategy to use when counting the users.
	 *                              Accepts either 'time' or 'memory'. Default 'time'.
	 * @param int|null    $site_id  Optional. The site ID to count users for. Defaults to the current site.
	 */
	$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() && $site_id != get_current_blog_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;
}

Top ↑

Changelog Changelog

Changelog
Version Description
4.9.0 The $site_id parameter was added to support multisite.
4.4.0 The number of users with no role is now included in the none element.
3.0.0 Introduced.


Top ↑

User Contributed Notes User Contributed Notes

  1. Skip to note 1 content
    Contributed by 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:

    There are 199 total users, 11 are administrators, 4 are contributors.
    

You must log in before being able to contribute a note or feedback.