How To Use WP_User_Query For WordPress User Queries

Earlier this week, I published a post on how to find users in WordPress by using meta data. In short, I have a collection of users each of which have unique meta data and I needed to locate a user based on said meta data.

In the comments, Curtis of @WPThemeTut recommended I check out WP_User_Query as opposed to way that I was doing it (which I’ll cover momentarily).

Because the WordPress API has a tendency to introduce new functions for querying specific data in later releases, and because I try to be a proponent of using the newer methods, I wanted to cover WP_User_Query in a bit more detail.

The Old Way

If you read my post from earlier this week, then you’ll currently see my function using WP_User_Query.

Originally, however, this is what I was doing:

function get_user_by_meta_data( $meta_key, $meta_value ) {

	// Set the critera for loading users
	$args = array(
		'meta_key'		=>	$meta_key,
		'meta_value'	=>	$meta_value
	);

	// Get the users and store the user returned by the query
	$users = get_users( $args );
	$user = empty ( $users[0] ) ? null : $users[0];

	return $user;

} // end get_user_by_meta_data

Simple enough – it’s nothing more than a call to get_users and then passing in an array of parameters on which to search, but rather than returning the array of users, it returns the first one.

Of course, you could generalize it and have it return $users. Either way, that’s beside the point.

The New Way

After Curtis’s suggestion, I ended up implementing the above function like this:

function get_user_by_meta_data( $meta_key, $meta_value ) {

	// Query for users based on the meta data
	$user_query = new WP_User_Query(
		array(
			'meta_key'	  =>	$meta_key,
			'meta_value'	=>	$meta_value
		)
	);

	// Get the results from the query, returning the first user
	$users = $user_query->get_results();

	return $user = empty ( $users[0] ) ? null : $users[0];

} // end get_user_by_meta_data

Subtle differences, right? Again, you could just as easily return $user_query->get_results() rather than the first user that matches the search, but that’s neither here nor there.

But Why?

The first way worked fine, so why swap to the new method? Simply put, WordPress has been introducing new features to its API with each new release. Recall that The Right Way™ was once to use query_posts in order to retrieve post data.

However, as of recent releases, WP_Query has become The Right Way™ to do it. It’s a cleaner interface, more powerful, and is the way that’s backed by Automattic and the developer community at large for properly querying the database for a variety of data.

All of that to say that this is strikingly similar – just as we’ve got from query_posts to WP_Query, we’re going from get_users to WP_User_Query.

It’s all about forward thinking.

The Details on WP_User_Query

The Codex article will provide much more information that I have below; however, I want to make sure that I highlight exactly what WP_User_Query offers if for no other reason to remind myself of what it can do.

Straight from the documentation:

The WordPress User Query class allows querying the user database and deprecates the WP_User_Search class since Version 3.1.

WP_User_Query…

  • An array of arguments from which it will use to query the database for results
  • Returns either an array of row objects or an array of user objects

To use the class – as with many in the WordPress API – you define the array of arguments and then pass them to the constructor of the WP_User_Query while instantiating the class. Assuming that your arguments are stored in an array referenced by $args, it would look like this:

  • $user_query = new WP_User_Query( $args );

Then, to get your array of results, you’d call:

  • $user_query->get_results()

Easy, isn’t it?

Overall, I’m a fan of this graduate shift to class-based queries rather than using global-level functions, but that’s because I’m more of a fan of object-oriented programming.

Regardless, this is the new way to query for users so consider this a heads up and start using it in new projects :).

14 Comments

Tom, great writeup! WP_User_Query is definitely a useful class for working with user queries. I can’t imagine having to work with sophisticated user queries without using it.

I just wanted to note that it is still appropriate to be using get_users(), even when we have WP_User_Query available. In fact, get_users() is the right way to do it! If you look at the Changelog for get_users(), you’ll notice that it was originally released in the same version with WP_User_Query, so basically get_users() is a wrapper function for WP_User_Query. Also, notice that in get_users()‘s code, WP_User_Query is being used for handling the query, and then for returning the results using the get_results() class method.

Most often I prefer to use the object-oriented way, but when I there is a wrapper function available, like get_users(), I tend to use them since they help saving up a couple lines of code (lazy me!).

Here’s a challenge I had not too long ago, where I was looking to query users by display name (A column in the wp_users table), which isn’t natively supported by WP_User_Query, yet. I had to dig up that class, and it was fun.

    This is a good comment – you definitely bring up a good point in claiming that it’s also the right way. In my experience with the WordPress community, people often get so concerned with the right way / wrong way of doing something, that I can take it too far.

    Obviously, right? :)

    I gotta say, though, as I’ve begun to use WP_Query more often, because I have a slight bias towards object-oriented programming, and since get_users is really just a wrapper, I lean more toward using WP_User_Query.

    Just like you prefer get_users, I opt for the alternative – no big deal there.

    Either way, this is good stuff and I appreciate you sharing it!

    I came here to say the exact same thing, good comment Maor and great post Tom! It’s just like get_posts versus WP_Query. Both are doing the exact same thing, but one or the other may be preferred in certain situations. If you need to query by the fields in the users table, you can also use the older wrapper function get_user_by.

    Also note, that before picking the 0-th index in the returned object, you should check whether it’s empty, otherwise you’ll end up with undefined index notices when querying with no results.

    Have a great week!
    Konstantin

      Thanks Konstantin!

      I actually still use the get_user_by function in very certain situations, but I still stay torn on whether I like having so many ways to do technically the same thing. But that’s another post for another time.

      At any rate, I went ahead and updated the code for the 0-th index. That one is kind of a given (and in the situation from which I was pull this post, it wasn’t going to be a problem), so thanks for pointing that out!

Doing things The Right Way™ means you get to take advantage of new features as they’re added too. Like the new get and set methods for WP_User_Query coming in WordPress 3.5 :)

    Based on Maor’s comment, I’m guessing that get_users will inherit all of that same functionality, too considering it’s a true wrapper.

    Though I do sometimes wonder why there are multiple ways to achieve the same thing. In some ways, I get shorter code, using it in the context of iterators, etc, but I’m also a fan of having a way to do it than ways to do it.

    Of course, that might just be the opinionated developer-side of me talking…

Over all I think WP_User_Query is better to use, but for no other reason than that is encourages consistency with methods like WP_Query.

The get_users() function does nothing more than take the passed arguments, send then to WP_User_Query and return the results.

In terms of efficiency and what kind of data you can retrieve, they are identical, with the exception of WP_User_Query having a few things you can do instead of just returning the results.

I agree with Maor here. I think the get_users() is more like get_posts() then query_posts(). Its just a simple wrapper function rather than the ‘wrong way’.

Like get_posts() it saves on the odd database query: just as get_posts() doesn’t bother with pagination / sticky post queries – so get_users() doesn’t bother counting the total number of users. So if you don’t need that information, I’d be tempted to stick with get_users().

    As I mentioned to Maor and Pippin, I tend to lean in the direction of using the object-oriented approach out of my own biases and out of consistency with other parts of the API.

    But your analogy of query_posts versus get_posts is spot on so thanks for pointing that out!

Hi Tom,

I’m trying to write a function that will return a list of users that have a certain role and a certain custom meta value. So far, my code doesn’t work. Can I hire you to help me?

Thanks for this. I was just looking to do this and dug up some old and sloppy code I wrote long ago and was wondering if it was still a reasonably good way to do it. Looks like it is. The slight difference being that I want to output users in groups by role. It’s always embarrassing to share code that one KNOWS it isn’t as efficient as it could be, but maybe it’ll still help someone (I’m sure I should be doing one user query and some sort of array sort instead of querying users for each role.) https://gist.github.com/jb510/f6ea0073b2dc18a79640

    It’s always embarrassing to share code that one KNOWS it isn’t as efficient as it could be, but maybe it’ll still help someone (I’m sure I should be doing one user query and some sort of array sort instead of querying users for each role.)

    Agreed, but it’s how we ultimately get better, you know? Gotta show off our weakness and let others help us get better at what we do.

Leave a Reply

Name and email address are required. Your email address will not be published.

You may use these HTML tags and attributes:

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