GeneratorsQueryUser Query Builder

User Query Builder

Query users by role, capability, meta and search — with the role vs role__in mixup and the count_total cost called out before you ship it.

user-query.php
Saved just now
Who
2 roles · role__in
Wrap in * for a wildcard. Without one it is an exact match.
Meta clauses
none
No meta clauses. User meta lives in one big table — filtering on it is a JOIN per clause, same as posts.
Shape of the result
count_total
Runs a second COUNT query so get_total() has a number.
has_published_posts
Only users who have actually published something.
The class, with get_results() and the total when you need pagination.
// Generated with WP CodeKit — powered by GrowQuest (https://growquest.io).
$args = array(
	'role__in'            => array( 'author', 'editor' ),
	'number'              => 20,
	'orderby'             => 'display_name',
	'has_published_posts' => true,
);

$query = new WP_User_Query( $args );

$total = $query->get_total();

if ( ! empty( $query->get_results() ) ) {
	echo '<ul>';

	foreach ( $query->get_results() as $user ) {
		printf(
			'<li><a href="%1$s">%2$s</a></li>',
			esc_url( get_author_posts_url( $user->ID ) ),
			esc_html( $user->display_name )
		);
	}

	echo '</ul>';

	printf(
		'<p>%s</p>',
		esc_html( sprintf( _n( '%s user', '%s users', $total, 'mytheme' ), number_format_i18n( $total ) ) )
	);
} else {
	esc_html_e( 'No users matched.', 'mytheme' );
}

About this generator

WP_User_Query Generator Online

Build a wp_user_query from a form: roles with the correct role, role__in or role__not_in argument, a capability filter, a wildcard search scoped to one column, user meta clauses, and the fields, number and count_total settings that decide how much memory the result takes. Out comes the class with get_results(), a get_users() one-liner, or just the args array.

A Reference tab restates the filter in plain English, documents every argument with its type, and shows the get_total() pagination pattern. Free, no account, and nothing you enter is sent anywhere.

Reviewed Output tested on WordPress 6.8 · PHP 8.3

Why the WP_User_Query builder beats a copied args array

Two defaults in this class surprise almost everyone. number defaults to -1, so a query with no limit returns every account on the site. And role is an inclusive list — passing two roles asks for users who hold both at once, which on most sites is nobody. The generator turns both into visible checks rather than a mystery empty result.

role versus role__in caught as an error

Listing more than one role while the mode is role is an error stating the consequence — a user must hold all of them at once — with a one-click switch to role__in, which is what "any of these" actually means.

The missing limit is flagged

WP_User_Query has no default page size; leaving number unset or at -1 returns every matching row. Both raise a warning with a "Limit to 20" fix, which is the difference between a fast query and a memory exhaustion on a membership site.

Search wildcards made explicit

A search term without * is an exact column match, which is rarely what people expect. The generator says so and offers to wrap the term — *@example.com — while a bare * on its own is an error, because it scans the entire users table.

count_total priced honestly

count_total is on by default and costs a second COUNT query. For a fixed-size list whose total is never displayed, the generator offers to turn it off; when you keep it, the output includes the get_total() call and a translated count string.

fields kept proportionate to the job

fields => all hydrates a full WP_User object per row and loads its meta. Asking for more than a hundred of those gets a tip to switch to ids, display_name or user_email, with a one-click fix — and the generated loop changes shape to match the flat values you get back.

Role internals left to core

A meta clause that targets wp_capabilities directly is flagged, because the role arguments already do that properly — including the per-site table prefix on multisite, which a hand-written clause gets wrong on every subsite.

How does the user query generator work?

Say who you want, add any profile-field conditions, then decide how much of each user you actually need back.

  1. 01

    Choose who

    Tick the roles — administrator, editor, author, contributor, subscriber, customer, shop_manager — and pick whether they are matched with role__in, role or role__not_in. Add a capability instead when what you mean is "anyone who can do X".

  2. 02

    Narrow it further

    Add a search term and optionally restrict it to one column, and add meta clauses for profile fields. One clause emits the meta_key / meta_value / meta_compare shorthand; two or more emit a full meta_query with a relation.

  3. 03

    Shape the result

    Set number, choose fields, pick the orderby and direction, and decide whether you need count_total and has_published_posts.

  4. 04

    Clear the checks, then export

    Apply the suggested fixes, then take the WP_User_Query class with its loop, the equivalent get_users() call, or the args array on its own.

Worked example — an author list of editors and authors who have actually published

Anyone in either role, ordered by display name, capped at twenty. has_published_posts drops accounts that have never written anything, and count_total is off because nothing on the page shows a total.

$args = array(
	'role__in'            => array( 'author', 'editor' ),
	'number'              => 20,
	'orderby'             => 'display_name',
	'count_total'         => false,
	'has_published_posts' => true,
);

$query = new WP_User_Query( $args );

if ( ! empty( $query->get_results() ) ) {
	echo '<ul>';

	foreach ( $query->get_results() as $user ) {
		printf(
			'<li><a href="%1$s">%2$s</a></li>',
			esc_url( get_author_posts_url( $user->ID ) ),
			esc_html( $user->display_name )
		);
	}

	echo '</ul>';
} else {
	esc_html_e( 'No users matched.', 'mytheme' );
}

Turn count_total back on and the generator adds $query->get_total() above the loop plus a properly pluralised, translated count below it — which is the only reason to pay for that second query.

WP_User_Query — frequently asked questions

What developers ask when a user list comes back empty, or far larger than expected.

What is the difference between role, role__in and role__not_in?

role is an inclusive list: a user must hold every role you pass, which is why role => array( "editor", "author" ) usually returns nobody. role__in matches users holding at least one of the listed roles, which is what people almost always mean. role__not_in excludes anyone holding any of them. role__in and role__not_in were added in WordPress 4.4.

How do I query users by capability instead of role?

Use the capability, capability__in or capability__not_in arguments, added in WordPress 5.9. They resolve to every role that grants the capability, plus users who have it assigned directly. The caveat in core is explicit: they cannot see capabilities that only exist through a map_meta_cap filter and were never written to the database, so a purely virtual capability will not match.

Why does my user query return every user on the site?

Because number defaults to -1, meaning no limit. Unlike WP_Query, there is no built-in page size, so a query with only a role filter returns every matching account and builds a WP_User object for each. Always set number, and pair it with paged or offset if you need more than the first page.

How do I search users by part of an email address?

Wrap the term in asterisks: search => "*@example.com". Without a * the comparison is an exact match on the column. Leading, trailing or both are supported, and a leading wildcard prevents MySQL from using the index. Restrict search_columns to user_email so the query does not also scan login, nicename, URL and display name.

How do I paginate a WP_User_Query?

Keep count_total on, set number to your page size and paged to the page you want, then read $query->get_total() for the total and divide to get the page count. count_total runs a second COUNT query, so turn it off on any list that shows no total — for a fixed "top ten authors" block that number is never displayed and never worth the query.

Should I use get_users() or WP_User_Query?

get_users() is a thin wrapper that instantiates the class, calls it and returns the results array. Use it when you just need the rows. Use the class directly when you need the total for pagination, or want to inspect the built SQL — the wrapper gives you no access to get_total().

Where do I paste the code from the WP_User_Query generator?

You have three good options and one bad one. Best is a small site-specific plugin — the generator can output one for you, and it keeps working when you change theme. A code-snippets plugin is fine too. A child theme's functions.php works but ties the code to that theme. Never edit the parent theme: the next update overwrites it and your code is gone.

Can I use the generated code in client work or a commercial plugin?

Yes. The output is ordinary WordPress API calls that you configured — there is no licence attached to it and no attribution required. Use it in client sites, commercial plugins and themes, or products you sell. The generated file carries a short credit comment you are free to delete.

The other Query generators in the library, plus the WordPress tools most often used alongside this one.