Working with Multiple User Metadata Queries

gold microphone condensers

With all of the work that’s being done on the Block Editor and Site Editor, it’s easy – and interesting – to focus on the new features that are going into WordPress. But one of the things something like this does is also allow divert our attention to some of the features that are already part of WordPress that may not be as familiar to those of us who have been around a while or even known to newcomers.

For example, if you’ve been working in WordPress for a long time especially when it comes to PHP, then you’re likely familiar with WP_Query and what it can do for your themes, plugins, and add-ons. And as WordPress continues to move in a direction that allows to work with it in a headless capacity, it’s helpful to learn and/or remember the things that WordPress still allows us to do.

And if you’re interested in tying this back into Headless WordPress, then we can continue to learn how to manipulate the administrative area and take that knowledge also build custom queries to grab custom result sets to be returned to the de-coupled frontend via the REST API. But I digress.


Anyway, case in point: I’ve needed to do some some work on customizing the administration area of the All Users screen in WordPress. To do this, I needed to heavily rely on custom user metadata. Here’s the thing, though: I’ve not needed to use just one piece of data. To customize the screen, I’ve needed to utilize several pieces of user metadata.

And in doing this, I started thinking about some of the things many of us are still doing with the backend of WordPress but either not talking about it, not having it publicized, or both.

So why not do both and discuss it here?

Ultimately, this is the type of backend work I think PHP developers and those who are working with WordPress in a variety of different ways should understand, I’m going to be writing a short tutorial series here for The WP Minute that’s covers how to work with WP_Query, user meta data, the All Users screen, and ultimately show how we can use this in a broader scope to enhance headless applications.

🎬 Introduction

The purpose of the rest of this article is going to cover how to retrieve records in a custom way by using built-in WordPress API functions that don’t require writing custom SQL.

Specifically, we’re going to talk about how to change how the All Users page is displays users through the use a custom meta query. First, we’re going to work with a single piece of metadata, then we’re going to look at how to modify the query to work with more than one piece of metadata. Secondly, we’re going to be working with two custom pieces of metadata: status and user_nickname. The first is one that can be customized to your liking. That is, you can insert records that render them as active or inactive or using values such as 1 or 2. Ans the other has to do with whether or not we’ve “deleted” them from the system (that is, think of them as a soft delete rather than completely removing their information).

The challenge in writing something like this, though, is that not everyone is going to have that custom metadata readily available. But WordPress does store user metadata right out-of-the-box. So in demonstrating how to this with our own metadata, we can use what WordPress provides as a starting point.

🪝 Understanding pre_get_users Hook

Whenever the All Users page is rendered, a set of core WordPress functions fire that retrieve all kinds of information about the users that are in the database. This includes, but is not limited to, their first name, last name, user name, email address, and more.

To do this, the WordPress application uses the WP_User_Query class. In short, this class is responsible for querying users.

The passed WP_User_Query object contains the query variables, not yet passed into SQL.

Let’s assume we want to change the way this page displays the results in a way that differs from what it does out of the box. That is, rather than render users the default order, maybe we want to use some piece of metadata – custom or not – that dictates what we see.

This is where the pre_get_users hook comes into the picture. This allows us to manipulate the query that’s going to ultimately run before it runs so the way information is retrieved from the database is set to suit our needs.

🔎 Verify We’re on the Right Page

Whenever we’re working on a plugin or feature that’s going to run within the administration area, it’s a good practice always make sure that we’re on the right page; otherwise, we run the risk of running the query on every single page and that can hurt performance.

So, naturally, it’s helpful to run an is_admin check. Recall, this function does the following:

Determines whether the current request is for an administrative interface page. Does not check if the user is an administrator; use current_user_can() for checking roles and capabilities.

In this article, though, we’re specifically looking at the All Users page so it stands to reason that we also want to make sure we’re only running on the users.php page that exists in WordPress.

To do this, it’s helpful to write a function that runs both checks:

function isOnUsersPage()
{
    return (
			is_admin() && 
			str_contains($_SERVER['REQUEST_URI'], 'users.php')
		);
}

Whenever you want to make sure you’re on the users page, then you can call this function anywhere in your code.

For example, the initial function we have may look like this:

add_action( 'pre_get_users', function ($query) { if (!isOnUsersPage()) { return $query; } // TODO... return $query; } );
Code language: PHP (php)

Of course, this doesn’t actually do anything other that verify the code we’re going to write runs in the administration area on the users.php page. And in the next article in this series, we’ll talk about exactly that.

📚 References

Is WordPress becoming less ‘pluggable’?
Here’s What I’d Love to See from WordPress in 2023