Steve Taylor photo

Get WordPress users by role

Please note that as of WordPress 3.1, this code is pretty much redundant. Check out get_users!

There’s a few posts around that reveal a nifty use of the WP_User_Search class that’s part of WordPress’ core code, in order to select all users that have a specific role (the trick seems to have originated with John Kolbert).

But… WP_User_Search is only loaded when you’re inside the WP admin area. What about front-end template code?

I decided to track down the SQL that WP_User_Search comes up with for the search (using $wpdb->queries), and write a custom function wrapper which will work the same way wherever.

I’m not quite sure if there’s any advantage to including the use of WP_User_Search as well as the back-up SQL, as they pretty much do the same thing. I dunno.

Anyway, here’s the code. This is for pasting into your theme’s functions.php file. It’ll return an array of user IDs.

function getUsersByRole( $role ) {
	if ( class_exists( 'WP_User_Search' ) ) {
		$wp_user_search = new WP_User_Search( '', '', $role );
		$userIDs = $wp_user_search->get_results();
	} else {
		global $wpdb;
		$userIDs = $wpdb->get_col('
			FROM '.$wpdb->users.' INNER JOIN '.$wpdb->usermeta.'
			ON '.$wpdb->users.'.ID = '.$wpdb->usermeta.'.user_id
			WHERE '.$wpdb->usermeta.'.meta_key = ''.$wpdb->prefix.'capabilities'
			AND '.$wpdb->usermeta.'.meta_value LIKE '%"'.$role.'"%'
	return $userIDs;

UPDATE 4/9/10: By popular request, here’s another version, which will accept an array (or comma-delimited list) of roles to select by. I’ve pasted it in from a custom project—do let me know if it works in your themes!

UPDATE 7/11/10: Thanks to Acebone, a corrected version that uses array_walk properly.

function getUsersByRole( $roles ) {
	global $wpdb;
	if ( ! is_array( $roles ) ) {
		$roles = explode( ",", $roles );
		array_walk( $roles, 'trim' );
	$sql = '
		SELECT	ID, display_name
		FROM		' . $wpdb->users . ' INNER JOIN ' . $wpdb->usermeta . '
		ON		' . $wpdb->users . '.ID				=		' . $wpdb->usermeta . '.user_id
		WHERE	' . $wpdb->usermeta . '.meta_key		=		'' . $wpdb->prefix . 'capabilities'
		AND		(
	$i = 1;
	foreach ( $roles as $role ) {
		$sql .= ' ' . $wpdb->usermeta . '.meta_value	LIKE	'%"' . $role . '"%' ';
		if ( $i < count( $roles ) ) $sql .= ' OR ';
	$sql .= ' ) ';
	$sql .= ' ORDER BY display_name ';
	$userIDs = $wpdb->get_col( $sql );
	return $userIDs;


  1. Ian avatar Ian

    You can also just include the WP_User_Search class from your template:

    require_once(WP_CONTENT_DIR . ‘/../wp-admin/includes/user.php’);

  2. Dwaynne avatar Dwaynne

    Ok, so how do you use this in a template function, since that’s where the rubber hits the road in displaying it to end-users?

  3. Hi Dwaynne, not sure if you’re asking me or Ian – I should get threaded comments sorted out here!

    As to how to use getUsersByRole, how about:

    $subscriberIDs = getUsersByRole( 'subscriber' );

    Then… depends what you want to do really.

  4. Flick avatar Flick

    Thanks for this code! I found out about it through CogDogBlog, and was wondering if multiple roles could be used in the getUsersByRole() bracket?

    This is because I would like to be able to display a list of users. e.g. all users excluding ‘subscriber’; or just display ‘editors’ and ‘authors’ together.

    At present I can only seem to search for ‘one’ role only.

    Thanks in advance! :)

  5. Hi Flick, check the updated post. I developed the alternate version for a project I worked on and never posted it. Hope it helps!

  6. Steve,

    Thanks for this post, it was very helpful.

    However, your update does not accept an array of roles, it accepts a comma separated string of roles (without any whitespace). A simple edit will allow comma separated strings (with or without whitespace) and arrays of roles. I replaced

    $roles = explode( ",", $roles );


    if( !is_Array( $roles ) ) {
    $roles = array_walk(explode( ",", $roles ), 'trim');

  7. Acebone avatar Acebone


    Your updated ‘array’ version of the function won’t work.

    array_walk does NOT return an array, it returns an error-value where 1 = true = everything went OK and 0 = false = something went wrong

    array_walk works directly on the array that you pass it (and you are passing it a temporary variable created by ‘explode’), so you need to change line 4.

    Here is a working version of your function:

    function getUsersByRole( $roles ) {
    global $wpdb;

    if ( !is_array( $roles ) ) {
    $roles = explode( ",", $roles );
    array_walk( $roles, 'trim' );

    $sql = '
    SELECT ID, display_name
    FROM ' . $wpdb->users . ' INNER JOIN ' . $wpdb->usermeta . '
    ON ' . $wpdb->users . '.ID = ' . $wpdb->usermeta . '.user_id
    WHERE ' . $wpdb->usermeta . '.meta_key = \'' . $wpdb->prefix . 'capabilities\'
    AND (

    $i = 1;
    foreach ( $roles as $role ) {
    $sql .= ' ' . $wpdb->usermeta . '.meta_value LIKE \'%"' . $role . '"%\' ';
    if ( $i get_col( $sql );

    return $userIDs;

    A quick test seems to confirm that this function works, haven’t tested in depth though,

  8. Acebone avatar Acebone

    That kind of thing happens.

    The SQL part itself, did you use it and can confirm that it works with no bugs?

    It seems to work, but I haven’t the time right now for proper testing.

    Another thing:

    WP_User_Search will return users with AT LEAST the specified role – so if you search ‘editors’ you get editors AND admins

    Your function seems to go directly for the specified user-role and nothing else, eg: editors but NOT admins

    If that’s true – I like your function better :)

  9. I can confirm that the SQL in the first example works fine. The second variant seems pretty straightforward, but I don’t have time for extensive testing, so let me know if it trips up anywhere.

    As for WP_User_Search, for me it only returns users in the specified role. Looking at the source, this does seem to be how it works. Let me know if you can confirm a situation where this isn’t the case.

    Interestingly, it seem that WP_User_Search has been deprecated for the next version of WP. I’ve not looked into how its replacement works.

  10. Jim avatar Jim

    Really cool Steve been trying to write code similar to this myself (but not trying too hard) luckily found you could while doing my research and now I can get to bed early! You’re a prince!

  11. Thanks for this code! I haven’t tested it yet but i’m sure it works.
    It saves me a lot of time!
    Many Thanks

  12. John Franks avatar John Franks

    You don’t know how much time you saved me. I had a site up that used basically the same code that you wrote. It would select all users in a role.

    Anyways the site got infected with a virus and I decided to scratch it and start over. Unfortunately I didn’t have a backup and lost the code.

    I was really dreading to have to rewrite it. But thankfully, I found your site now I don’t have to.

  13. rayne avatar rayne

    Thanks for this script! I found it while I was looking for a way to “gray out” inactive authors – I want a list of authors where every author who hasn’t posted anything in the last 6 or 12 months is applied an extra CSS class (eg. gray font color or 50% opacity). Would that be easy to implement into your script? My PHP skills are too crappy to figure it out myself :/

  14. Hi rayne, sounds like you need some custom SQL querying. Or, if you don’t mind the extra database hits (or you have a caching plugin working and it doesn’t matter), just grab the most recent post for each author in the loop as you output them, and test the date. HTH.

  15. Kexin Li avatar Kexin Li

    Hi Steve,

    Thanks for sharing the plugin. Can you please tell me how I can call this function on my template? For example I want to list all administrators

  16. pardeep avatar pardeep

    Parse error: syntax error, unexpected ” . $wpdb->prefix . ” (T_CONSTANT_ENCAPSED_STRING)

  17. Steve Taylor avatar Steve Taylor

    Thanks, but as stated, this code is 9 years old and is redundant. I’m not maintaining it.

Comments are closed.