pre_user_query tutorial: hiding the user with the exact ID, hiding the users by the role, extending the user search

First of all you should know one important moment. There are two base user query action hooks:

  1. pre_get_users — it fires before WP_User_Query has been parsed and allows you to change some query vars like include, exclude, order, orderby etc.
  2. pre_user_query fires after the user query has been parsed but before the query is executed. Do you see the difference?

Let’s begin with the base example, just copy the following code to your current theme functions.php file and open a page with the user list. It can be your administration «Users» page.

add_action( 'pre_user_query', 'rudr_pre_user_query_base_example' );

function rudr_pre_user_query_base_example( $u_query ){
	print_r( $u_query );
}

I hope you already know what print_r() function is.

And one more thing, if your WordPress version is lower that 3.1, the following examples won’t work for you (try to use pre_user_search instead or update your WordPress).

1. How to completely hide the user with the exact ID from your website.

Okay, this user will not be displayed on the website or inside administration area at all. How to archieve it? With the help of pre_user_query of course.

add_action('pre_user_query','rudr_completely_hide_user');

function rudr_completely_hide_user( $u_query ) {
	
	// let's allow the hidden user to see himself
	$current_user = wp_get_current_user();
	if ($current_user->ID != 2) { // the user with ID = 2 for example
		global $wpdb;
		// just str_replace() the SQL query 
		$u_query->query_where = str_replace('WHERE 1=1', "WHERE 1=1 AND {$wpdb->users}.ID<>2", $u_query->query_where); // do not forget to change user ID here as well
	}

}

2. How to remove the ability for other users to view administrators in user lists?

It is the more interesting example than the previous one, it based on the same principle, but you can see the complex SQL query in it.

add_action('pre_user_query','rudr_hide_all_administrators');

function rudr_hide_all_administrators( $u_query ) {
	
	// let's do the trick only for non-administrators
	$current_user = wp_get_current_user();
	if ( $current_user->roles[0] != 'administrator' ) { 
		global $wpdb;
		$u_query->query_where = str_replace(
			'WHERE 1=1', 
			"WHERE 1=1 AND {$wpdb->users}.ID IN (
				SELECT {$wpdb->usermeta}.user_id FROM $wpdb->usermeta 
					WHERE {$wpdb->usermeta}.meta_key = '{$wpdb->prefix}capabilities'
					AND {$wpdb->usermeta}.meta_value NOT LIKE '%administrator%')", 
			$u_query->query_where
		);
	}
}

Perhaps you know that user roles are stored in wp_usermeta table (change wp_ to your database prefix) under the wp_capabilities meta_key. So, in the example above we got all the users which has administrator word in their wp_capabilities values.

3. Extend the user search by custom meta_keys from wp_usermeta or custom columns from the other tables.

By default WordPress allows to search users by predefined columns (user_login, user_email, user_url, display_name, ID and user_nicename). You can also use the user_search_columns filter to exclude some of the predefined columns from the search.

But pre_user_query allows you to search by a first name, a last name, another user meta key or take wp_posts table for example and search by post titles, this user has been published.

add_action('pre_user_query','rudr_extend_user_search');


function rudr_extend_user_search( $u_query ){
	// make sure that this code will be applied only for user search
	if ( $u_query->query_vars['search'] ){
		$search_query = trim( $u_query->query_vars['search'], '*' );
		if ( $_REQUEST['s'] == $search_query ){
			global $wpdb;
 	
 			// let's search by users first name
			$u_query->query_from .= " JOIN {$wpdb->usermeta} fname ON fname.user_id = {$wpdb->users}.ID AND fname.meta_key = 'first_name'";
			
			// you can add here any meta key you want to search by
			// $u_query->query_from .= " JOIN {$wpdb->usermeta} cstm ON cstm.user_id = {$wpdb->users}.ID AND cstm.meta_key = 'YOU CUSTOM meta_key'";
 	
 			// let's search by all the post titles, the user has been published
			$u_query->query_from .= " JOIN {$wpdb->posts} psts ON psts.post_author = {$wpdb->users}.ID";
			
 			// what fields to include in the search
 			$search_by = array( 'user_login', 'user_email', 'fname.meta_value', 'psts.post_title' );
 			
 			// apply to the query
			$u_query->query_where = 'WHERE 1=1' . $u_query->get_search_sql( $search_query, $search_by, 'both' );
		}
	}
}
Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on Twitter