Sort users by numeric value in Users Screen

By default you can sort users in Users Screen by username, name, email and role.

Users Screen

Sort users based on numeric value

What if we wanted to sort users based on numeric value? Value can be for example age or expire date. First we’d need to save numeric info in *_usermeta table. There are handy functions like add_user_meta and update_user_meta for doing that. But it’s outside of this tutorial. Let’s focus on how you can manage custom sortable columns and sort by meta_value_num.

There are four steps we need to take:

  1. Add new custom user column using manage_users_columns.
  2. Add content to column using manage_users_custom_column.
  3. Make custom column sortable using manage_users_sortable_columns.
  4. Sort users based on numeric value in custom column using pre_get_users.

Add custom column

Let’s use expire date, which is stored as strtotime, as an example. First we add custom column using manage_users_columns filter.

/**
 * Add new user column: Expire Date.
 *
 * @since  1.0.0
 * @return array $columns
 */
function prefix_expire_date_column( $columns ) {
	$columns['expire_date']   = __( 'Expire Date', 'text-domain' );
	return $columns;
}
add_filter( 'manage_users_columns', 'prefix_expire_date_column' );

We add new column in users columns array in format name => label. In our case custom column name is expire_date. Let’s keep that in mind.

Add content to custom column

Next step is to add content in our custom column. We can do that using manage_users_custom_column filter. It has three parameters: $value, $column_name and $user_id.

/**
 * Adds Expire date and Status to column.
 *
 * @since  1.0.0
 * @return void
 */
function prefix_add_custom_columns( $value, $column_name, $user_id ) {
	
	if( 'expire_date' == $column_name ) {
		
		/* Get expire date somehow. For example using your custom function */
		$expire_date = prefix_get_expire_date( $user_id );
		
		$value = $expire_date;
	
	}
	
	return $value;
	
}
add_action( 'manage_users_custom_column', 'prefix_add_custom_columns', 10, 3 );

We want to add and return expire date value when our custom column name is the correct one, in our example it was expire_date. In short we first check that our column name is expire_date, then add your content and return the value.

Make custom column sortable

By default custom column is not sortable. Next we use manage_users_sortable_columns filter to make our custom column sortable.

/**
 * Add sortable columns.
 *
 * @since  1.0.0
 * @return void
 */
function prefix_sortable_columns( $columns ) {
	
	$columns['expire_date'] = 'expire_date';
	return $columns;
	
}
add_filter( 'manage_users_sortable_columns', 'prefix_sortable_columns' );

We use our expire_date column again and I prefer to give it the same name. It tells WordPress that our orderby parameter is expire_date and when you click the Expire date column our URL turns into this: users.php?orderby=expire_date&order=asc.

But the last step is the most important one.

Sort users based on numeric value

Even if we make custom columns sortable nothing really happens when you click the Expire date column. We have to tell WordPress how we want to sort. In WordPress 4.2 sorting by numeric value became much more easier in WP_User_Query. Here is core track ticket for more info.

It means that now we can use meta_value_num in orderby parameter (orderby=meta_value_num).

In the same time, or in WordPress 4.0.0, there is action hook called pre_get_users which we can use to sort based on numeric value in our custom user column.

/**
 * Sort by expire date. Meta key is called 'prefix_expiration_date'.
 *
 * @since  1.0.0
 * @return void
 */
function prefix_sort_by_expiration_date( $query ) {
	
	if ( 'expire_date' == $query->get( 'orderby' ) ) {
		$query->set( 'orderby', 'meta_value_num' );
		$query->set( 'meta_key', 'prefix_expiration_date' );
	}
}
add_action( 'pre_get_users', 'prefix_sort_by_expiration_date' );

We need three things for sorting:

  1. Firts check that our query orderby paramater is expire_date. Note that this could be named for something else but in our case it was the same as column name. We use get() method for retrieving query variable.
  2. Set orderby=meta_value_num because we wanted to sort by numeric value. We use set() method for setting the parameter.
  3. Set meta_key=your_meta_key_name. In our example meta_key is called prefix_expiration_date. In here we also use set() method.

You can check all the methods and properties in WP_User_Query codex page.

That’s it. We’re done.

Conclusion

It took me about two days to figure this out when I needed this feature in EDD Members add-on. Believe me, I tried everything and read every tutorial I could find. But still no luck. Then I did what I was suppose to do in the first place.

  • Ask help from Justin Tadlock in Themehybrid forums. I could have asked help in WordPress Stackexchange but I had a hunch that he’s been working on the same issue. And he did.
  • Dive in to the Core code. We would have never found the hook pre_get_users if it wasn’t right there in the Core code.

Justin also have excellent tutorial about Custom columns for custom post types.