UserQuery builds the arguments of WP_User_Query.
Read Concepts first, and Getting results for the terminal methods. Examples assume:
use Pollora\Query\UserQuery;- Defaults
- Roles and capabilities
- Selecting users
- Search
- Authors
- Order
- Limit and pagination
- Fields
- Meta and dates
- Performance
- Results
UserQuery::select()->get();WP_User_Query receives:
[
'fields' => 'all',
]The builder adds no constraint: WordPress returns every user, with no limit, and the full WP_User objects (fields => 'all').
| Method | WordPress argument | Matches users… |
|---|---|---|
role(string|array) |
role |
having every listed role |
roleIn(array) |
role__in |
having at least one of the roles |
roleNotIn(array) |
role__not_in |
having none of the roles |
capability(string|array) |
capability |
having every listed capability |
capabilityIn(array) |
capability__in |
having at least one |
capabilityNotIn(array) |
capability__not_in |
having none |
blogId(int) |
blog_id |
roles and capabilities are read on this site (multisite) |
Capabilities only work if they are stored in the database: those added by a plugin on the fly, or modified by map_meta_cap, are not found. capability('edit_posts') is the replacement of the deprecated who => 'authors', which UserQuery does not support.
UserQuery::select()->roleIn(['editor', 'author'])->get();WP_User_Query receives:
[
'fields' => 'all',
'role__in' => [
'editor',
'author',
],
]| Method | WordPress argument |
|---|---|
UserQuery::find(5), find([1, 2]) |
include |
whereIn(array) |
include |
whereNotIn(array) |
exclude |
login(string) |
login |
loginIn(array) / loginNotIn(array) |
login__in / login__not_in |
nicename(string) |
nicename |
nicenameIn(array) / nicenameNotIn(array) |
nicename__in / nicename__not_in |
An empty whereIn([]) is not "no result": WordPress ignores an empty include, so every user matches. Guard an empty list yourself.
| Method | WordPress argument |
|---|---|
search(string) |
search |
searchColumns(array) |
search_columns: among ID, user_login, user_email, user_url, user_nicename, display_name. Another column throws a QueryException. |
Without a *, the keyword must match a whole value. A leading *, a trailing *, or both, make it a partial match (*bob, bob*, *bob*).
Without searchColumns(), WordPress picks the columns from the keyword: an @ searches the email, a number the login and the ID, a URL the website, anything else the login, website, email, nicename and display name.
UserQuery::select()->search('*smith*')->searchColumns(['display_name', 'user_email'])->get();WP_User_Query receives:
[
'fields' => 'all',
'search' => '*smith*',
'search_columns' => [
'display_name',
'user_email',
],
]hasPublishedPosts() keeps the users who have published posts: in every public post type, or in the ones you give.
UserQuery::select()->hasPublishedPosts(['post', 'page'])->get();WP_User_Query receives:
[
'fields' => 'all',
'has_published_posts' => [
'post',
'page',
],
]orderBy($field, $direction = 'ASC') adds a sort key, in call order; it also takes a map of fields and directions. orderby is sent as a map, so each field has its own direction.
| Method | Sorts by |
|---|---|
orderBy($field, $direction) |
ID, display_name, user_login, user_nicename, user_email, user_url, user_registered, post_count, meta_value, meta_value_num, a meta key or a meta clause name |
orderByName() |
display_name |
orderByLogin() |
user_login |
orderByEmail() |
user_email |
orderByPostCount($direction = 'DESC') |
post_count |
latest() |
user_registered descending |
oldest() |
user_registered ascending |
orderByInclude() |
include: keep the order of whereIn() |
orderByLoginIn() |
login__in: keep the order of loginIn() |
orderByNicenameIn() |
nicename__in: keep the order of nicenameIn() |
orderByMeta($key, $direction, $numeric) |
meta_value or meta_value_num, and sets meta_key |
An invalid direction throws a QueryException.
UserQuery::select()->orderBy('display_name')->orderBy('user_registered', 'DESC')->get();WP_User_Query receives:
[
'fields' => 'all',
'orderby' => [
'display_name' => 'ASC',
'user_registered' => 'DESC',
],
]| Method | WordPress argument |
|---|---|
limit(int), take(int) |
number |
offset(int), skip(int) |
offset |
paged(int) |
paged: the page, used together with limit() |
UserQuery::select()->role('subscriber')->limit(20)->paged(3)->get();WP_User_Query receives:
[
'fields' => 'all',
'role' => 'subscriber',
'number' => 20,
'paged' => 3,
]fields() (or UserQuery::select(...)) takes 'all' (or '*'), one field, or an array of fields among ID, display_name, user_login, user_nicename, user_email, user_url, user_registered, user_pass, user_activation_key, user_status, spam and deleted. 'id' is read as 'ID'. An unknown field throws a QueryException, and so does 'all' combined with other fields.
UserQuery::select(['ID', 'user_email'])->role('editor')->get();WP_User_Query receives:
[
'fields' => [
'ID',
'user_email',
],
'role' => 'editor',
]metaKey(), metaValue(), metaQuery()… work as for posts: see Meta queries.
dateQuery() filters on the registration date (user_registered): see Date queries. Do not name a column: the default is the right one.
UserQuery::select()
->metaQuery(function (MetaQuery $query) {
$query->where($query->meta('plan')->equalTo('pro'));
})
->dateQuery(function (DateQuery $query) {
$query->where($query->date()->after('2024-01-01'));
})
->get();WP_User_Query receives:
[
'date_query' => [
'relation' => 'AND',
[
'after' => [
'year' => 2024,
'month' => 1,
'day' => 1,
'hour' => 0,
'minute' => 0,
'second' => 0,
],
],
],
'fields' => 'all',
'meta_query' => [
'relation' => 'AND',
[
'key' => 'plan',
'compare' => '=',
'type' => 'CHAR',
'value' => 'pro',
],
],
]| Method | WordPress argument | Notes |
|---|---|---|
cacheResults(bool = true) |
cache_results |
|
countTotal(bool = true) |
count_total |
Count the total number of users (WordPress does by default). |
withoutCount() |
count_total => false |
Faster when you do not paginate: get_total() is then 0. |
get() returns the WP_User_Query: read ->get_results() and ->get_total(). The terminal methods are:
$user = UserQuery::select()->login('admin')->first(); // WP_User|null
$ids = UserQuery::select()->role('editor')->ids(); // [2, 7, 9]
$emails = UserQuery::select()->role('subscriber')->pluck('user_email'); // ['a@x.test', ...]
$total = UserQuery::select()->role('subscriber')->count();
$has = UserQuery::select()->roleIn(['editor'])->exists();