Using WP_User_Query To Retrieve Users Across Multiple Roles

October 26, 2012 — 6 Comments

I’ve covered WP_User_Query in a previous post. In short, WP_User_Query is the preferred method for retrieving user information from the database when working with custom queries.

One of the shortcomings of this API method is that it doesn’t allow you to query across multiple roles. So, for example, if you want to retrieve users that meet a certain criteria but may span across multiple roles – say editors and administrators – the API doesn’t support it.

That said, there is a simple strategy that can be used with WP_User_Query to retrieve users across multiple roles.

A Real World Scenario

Before setting up the query, we need to define a scenario in which this may be useful. In one of my recent projects, all users accounts had a piece of meta data associated with them.

Specifically, users had a meta key of ‘featured’ and a value of ‘yes’ or a value of ‘no.’ In code, it worked something like this:

add_user_meta( $user_id, 'featured', 'yes' );

From there, users could either be set as administrators or as editors and I needed to pull back five featured users from each role and then render their display name on the frontend.

Ultimately, the final loop looked something like this:

foreach( $users as $user ) {
  echo $user->display_name;
} // end foreach

Simple, right? But there’s a bit that actually goes into collecting all of the users into that single array.

WP_User_Query and Multiple Roles

Given the state of some of the other API methods, I think that it’s a reasonable assumption that you could setup a call to WP_User_Query like this:

$editor_query = new WP_User_Query(
	array(
		'role'			    =>	array( 'editor', 'administrator' ),
		'meta_key' 		  => 'featured',
		'meta_value'	  =>	'yes',
		'meta_compare'	=>	'=',
		'number'		    =>	5
	)
);

But that’s not the case. The role parameter actually only accepts a single string, not an array.

Instead, you have to actually setup two separate queries and then merge the results into a single array:

// get the featured editors
$editor_query = new WP_User_Query(
	array(
		'role'			    =>	'editor',
		'meta_key' 		  => 'featured',
		'meta_value'	  =>	'yes',
		'meta_compare'	=>	'=',
		'number'		    =>	5
	)
);
$editors = $editor_query->get_results();

// get the featured admins
$administrator_query = new WP_User_Query(
	array(
		'role'			    =>	'administrator',
		'meta_key' 		  => 'featured',
		'meta_value'	  =>	'yes',
		'meta_compare'	=>	'=',
		'number'		    =>	5
	)
);
$admins = $administrator_query->get_results();

// store them all as users
$users = array_merge( $admins, $editors );

Obviously, it’s not the most elegant solution since you have to setup several independent queries, but it does provide a straightforward way of querying users across multiple roles, and then accessing them all from a single, independent query.

As usual, I’m always interested in how others address this issue especially if there’s a more optimal solution so let me know in the comments.

6 responses to Using WP_User_Query To Retrieve Users Across Multiple Roles

  1. it just so happens I was after this very thing recently, in the end I used get_users and removed admins with jquery, this is a much better solution thanks Tom.

    • Of course, Elliot – glad to help!

      When it comes to stuff like this, I generally think it’s better to do as much work on the server side since any clever end user that’s comfortable with a debug console could end up displaying some information that you intended to hide.

      In your case, it’s nothing too drastic though, so maybe I’m being a bit facetious ;) .

  2. Grant Kinney May 7, 2013 at 6:59 pm

    I found this solution by Andy Adams on the wordpress stackexchange site. It uses a meta query to pull users by their associated capabilities from the usermeta table. I think it works quite well for this task.


    global $wpdb;

    $user_query = new WP_User_Query( array(
    'meta_query' => array(
    'relation' => 'OR',
    array(
    'key' => $wpdb->prefix . 'capabilities',
    'value' => 'role_one',
    'compare' => 'like'
    ),
    array(
    'key' => $wpdb->prefix . 'capabilities',
    'value' => 'role_two',
    'compare' => 'like'
    )
    )
    ) );

    • Andy’s a great developer so thanks for sharing this. Love having a couple of different ways to perform the same task.

      The only thing with the code above is that I dislike the concatenation of the $wpdb->prefix with the string in the array. Honestly, it’s not that big of a deal – it’s a matter purely of personal preference. I’m picky like that :) .

      Nonetheless, I do appreciate you sharing this snippet as it does provide a bit of a more concise way of doing exactly this.

  3. Thanks a lot for this method! It was really helpful to me. Also, I tried both your method and Andy’s: yours is way faster.

    • Thanks for sharing this Julien!

      I can’t necessarily say why it’s faster without digging deeper and benchmarking, but I suspect that it has to do with the query optimization that comes with using WP_Query where as Andy’s method is using a combination of that and the $wpdb object.

      My general rule of thumb is to avoid $wpdb unless WP_Query or WP_User_Query absolutely cannot perform what I need.

Leave a Reply

*

Text formatting is available via select HTML.

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>