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: 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. pre_user_query fires after the user query has been parsed but before the query is executed. […]

  /  April 12  /   3

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
	}
 
}
  • You can move the if condition outside the function, like here:
    $current_user = wp_get_current_user();
    if ($current_user->ID != 2)
    	add_action('pre_user_query','rudr_completely_hide_user');
  • Nobody could see that user on the website, but please notice that the function don’t change user counts:
    Old user counts after hiding a user from the website.

    Do not worry about that — there are plenty of filters that can help you.

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' );
		}
	}
}

Only the best of WordPress

Subscribe to this weekly newsletter to receive the latest blog posts by email.I respect your privacy. Your email is safe with me.

Comments 3

  • Henrique Silvério August 13, 2016 at 01:22

    Hi Misha, thanks for the good tips and explanations!

    About the user counts you say:

    — “Do not worry about that — there are plenty of filters that can help you”.

    Can you mention what are they?

    For example: I like to exclude all users of a role in this count.

    • MishaAuthor August 13, 2016 at 07:26

      Hi Henrique,
      you could try this:

      add_filter('views_users', 'misha_change_user_count');
       
      function misha_change_user_count( $views ){
      	// here you can change the values in $views array, for example:
      	// $views['all']
      	// $views['administrator']
       
      	return $views; // return the result;
      }
      • Henrique Silvério August 13, 2016 at 19:26

        Thanks for reply! That’s what I need. =]

        Just sharing here, may be helpful for someone reading: Now I found in codex, that is a dynamic hook`views_{$this->screen->id}` (https://developer.wordpress.org/reference/hooks/views_this-screen-id).

Leave your question or feedback

phpjsHTMLCSSSQLCode
Please, enter a comment
Please, enter a name
Incorrect email