WP_User_Query Class
Core class for querying users with flexible filtering, sorting, and pagination.
Since: 3.1.0
Source: wp-includes/class-wp-user-query.php
Overview
WP_User_Query provides a powerful interface for retrieving users from the database with support for role/capability filtering, meta queries, search, and pagination.
Class Definition
#[AllowDynamicProperties]
class WP_User_Query {
public $query_vars = array();
private $results;
private $total_users = 0;
public $meta_query = false;
public $request;
// SQL clause properties
public $query_fields;
public $query_from;
public $query_where;
public $query_orderby;
public $query_limit;
}Constructor
public function __construct( null|string|array $query = null )If $query is provided, immediately prepares and executes the query.
Example:
$query = new WP_User_Query( array(
'role' => 'author',
'orderby' => 'registered',
'order' => 'DESC',
) );
$users = $query->get_results();Query Variables
Role & Capability Filtering
| Parameter | Type | Default | Description |
|---|---|---|---|
role | string|string[] | '' | Role(s) users must have (AND logic) |
role__in | string[] | [] | Roles to include (OR logic) |
role__not_in | string[] | [] | Roles to exclude |
capability | string|string[] | '' | Capabilities users must have (AND logic) |
capability__in | string[] | [] | Capabilities to include (OR logic) |
capability__not_in | string[] | [] | Capabilities to exclude |
Examples:
// Users with author role
'role' => 'author'
// Users with author OR editor role
'role__in' => array( 'author', 'editor' )
// Users with both roles (rare, but possible)
'role' => array( 'author', 'premium_member' )
// Users who can edit posts
'capability' => 'edit_posts'
// Exclude administrators
'role__not_in' => array( 'administrator' )Note: Capability queries only work for capabilities stored in the database, not those filtered via map_meta_cap.
ID Filtering
| Parameter | Type | Default | Description |
|---|---|---|---|
include | int[] | [] | User IDs to include |
exclude | int[] | [] | User IDs to exclude |
Login/Nicename Filtering
| Parameter | Type | Default | Description |
|---|---|---|---|
login | string | '' | Exact login match |
login__in | string[] | [] | Logins to include |
login__not_in | string[] | [] | Logins to exclude |
nicename | string | '' | Exact nicename match |
nicename__in | string[] | [] | Nicenames to include |
nicename__not_in | string[] | [] | Nicenames to exclude |
Search
| Parameter | Type | Default | Description |
|---|---|---|---|
search | string | '' | Search keyword |
search_columns | string[] | [] | Columns to search |
Search columns: 'ID', 'user_login', 'user_email', 'user_url', 'user_nicename', 'display_name'
Wildcards: Use * for leading/trailing wildcards.
// Search all relevant columns
'search' => '*john*'
// Search specific columns
'search' => 'john',
'search_columns' => array( 'user_login', 'display_name' )
// Email search (auto-detected)
'search' => '[email protected]'Meta Queries
| Parameter | Type | Default | Description |
|---|---|---|---|
meta_key | string|string[] | '' | Meta key(s) to filter |
meta_value | string|string[] | '' | Meta value(s) to filter |
meta_compare | string | '=' | Comparison operator |
meta_compare_key | string | '=' | Key comparison operator |
meta_type | string | 'CHAR' | Value data type for CAST |
meta_type_key | string | 'CHAR' | Key data type for CAST |
meta_query | array | [] | Full meta query array |
Example:
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'last_login',
'value' => strtotime( '-30 days' ),
'compare' => '>',
'type' => 'NUMERIC',
),
array(
'key' => 'subscription_status',
'value' => 'active',
),
)Sorting
| Parameter | Type | Default | Description |
|---|---|---|---|
orderby | string|array | 'login' | Field(s) to order by |
order | string | 'ASC' | Sort direction |
Orderby values:
| Value | Description |
|---|---|
'ID' / 'id' | User ID |
'login' / 'user_login' | Username |
'nicename' / 'user_nicename' | URL slug |
'email' / 'user_email' | |
'url' / 'user_url' | Website |
'registered' / 'user_registered' | Registration date |
'name' / 'display_name' | Display name |
'post_count' | Number of posts |
'meta_value' | Meta value (requires meta_key) |
'meta_value_num' | Meta value as number |
'include' | Preserve include order |
'login__in' | Preserve login__in order |
'nicename__in' | Preserve nicename__in order |
Multi-column sorting:
'orderby' => array(
'display_name' => 'ASC',
'ID' => 'DESC',
)Pagination
| Parameter | Type | Default | Description |
|---|---|---|---|
number | int | -1 | Users to return (-1 for all) |
offset | int | 0 | Users to skip |
paged | int | 1 | Page number |
count_total | bool | true | Count total users |
Example:
// Page 2, 20 per page
'number' => 20,
'paged' => 2,Fields
| Parameter | Type | Default | Description |
|---|---|---|---|
fields | string|string[] | 'all' | Fields to return |
Field options:
| Value | Returns |
|---|---|
'all' | Array of WP_User objects |
'ID' | Array of IDs |
'display_name' | Array of display names |
'user_login' | Array of logins |
| Array | Objects with specified fields |
// Just IDs
'fields' => 'ID'
// Specific fields
'fields' => array( 'ID', 'user_email', 'display_name' )Other Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
blog_id | int | Current | Site ID (multisite) |
has_published_posts | bool|string[] | null | Has published posts |
who | string | '' | Deprecated. Use capability |
cache_results | bool | true | Cache query results |
// Users with published posts
'has_published_posts' => true
// Users with published posts in specific types
'has_published_posts' => array( 'post', 'page' )Methods
prepare_query()
Prepares query variables.
public function prepare_query( string|array $query = array() ): voidCalled automatically by constructor, but can be called manually to reset query.
query()
Executes the query.
public function query(): voidSets $results and $total_users.
get_results()
Returns query results.
public function get_results(): arrayget_total()
Returns total user count (for pagination).
public function get_total(): intget()
Gets query variable.
public function get( string $query_var ): mixedset()
Sets query variable.
public function set( string $query_var, mixed $value ): voidfill_query_vars()
Fills missing vars with defaults.
public static function fill_query_vars( string|array $args ): arrayHooks
Actions
pre_get_users
Fires before query is parsed.
do_action_ref_array( 'pre_get_users', array( &$this ) );Example:
add_action( 'pre_get_users', function( $query ) {
if ( ! is_admin() ) {
$query->set( 'role', 'subscriber' );
}
} );pre_user_query
Fires after parsing, before execution.
do_action_ref_array( 'pre_user_query', array( &$this ) );Example:
add_action( 'pre_user_query', function( $query ) {
// Modify SQL directly
$query->query_where .= " AND user_status = 0";
} );Filters
users_pre_query
Short-circuits the query.
$results = apply_filters_ref_array( 'users_pre_query', array( null, &$this ) );Return non-null to bypass default query.
user_search_columns
Filters search columns.
$columns = apply_filters( 'user_search_columns', $columns, $search, $this );found_users_query
Filters the FOUND_ROWS() query.
$sql = apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()', $this );Usage Examples
Basic Query
$args = array(
'role' => 'subscriber',
'orderby' => 'registered',
'order' => 'DESC',
'number' => 10,
);
$user_query = new WP_User_Query( $args );
if ( ! empty( $user_query->get_results() ) ) {
foreach ( $user_query->get_results() as $user ) {
echo $user->display_name . '<br>';
}
} else {
echo 'No users found.';
}Paginated Query
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$per_page = 20;
$query = new WP_User_Query( array(
'number' => $per_page,
'paged' => $paged,
) );
$total = $query->get_total();
$pages = ceil( $total / $per_page );
echo "Showing page {$paged} of {$pages} ({$total} users total)";Complex Meta Query
$query = new WP_User_Query( array(
'meta_query' => array(
'relation' => 'AND',
'membership' => array(
'key' => 'membership_level',
'value' => array( 'gold', 'platinum' ),
'compare' => 'IN',
),
'active' => array(
'key' => 'last_login',
'value' => strtotime( '-90 days' ),
'compare' => '>',
'type' => 'NUMERIC',
),
),
'orderby' => 'membership',
'order' => 'DESC',
) );Search with Specific Columns
$query = new WP_User_Query( array(
'search' => '*smith*',
'search_columns' => array( 'user_login', 'user_email', 'display_name' ),
) );Get Just IDs
$query = new WP_User_Query( array(
'role' => 'editor',
'fields' => 'ID',
) );
$editor_ids = $query->get_results(); // [1, 5, 12, ...]Multisite: Users on Specific Site
$query = new WP_User_Query( array(
'blog_id' => 2,
'role' => 'author',
) );Authors with Published Posts
$query = new WP_User_Query( array(
'has_published_posts' => array( 'post' ),
'orderby' => 'post_count',
'order' => 'DESC',
'number' => 10,
) );Exclude Specific Users
$query = new WP_User_Query( array(
'exclude' => array( 1, 2, 3 ), // Exclude admin IDs
'role__not_in' => array( 'administrator' ),
) );Date-Based Query
$query = new WP_User_Query( array(
'date_query' => array(
array(
'after' => '2024-01-01',
'before' => '2024-12-31',
),
),
) );Performance Notes
Disable total count when not needed:
php'count_total' => falseCache is disabled when more than 3 fields requested.
Large queries should use pagination:
php'number' => 100, 'paged' => $page,Results are cached using salted cache keys based on query + last changed timestamps.