Practical WordPress Development

WP_Query Readability Improvements (For Maintenance)

Working with WP_Query, especially when you’re doing some custom work outside of the usual “get some posts and display them on a template” can be powerful. This is especially true of some of the advanced arguments (like using WP_Meta_Query, for example).

It’s also kind of nice that setting up the process has a standard way of doing things. Namely:

  1. Define the arguments,
  2. Instantiate WP_Query,
  3. Check if there are posts,
  4. Loop through them,
  5. Finish Them.

But if you get to where you’re doing any advanced work such as working with a custom post type from a third-party solution, having to sideload media, determine if something exists before actually doing any work with it, then it can be a little more complicated to work with, can’t it?

I’ve found that, like with anything in programming, breaking it down into much more readable modules (or functions or pieces or whatever you’d like to call them) can make it much easier to work with.

So here’s one way that I go about working to make WP_Query readability improvements in a variety of the stuff I’ve done lately.

WP_Query Readability Improvements

Before walking through any example, it’s worth pointing out that there are some things that the way WP_Query is setup that we can’t do.

For example, once the query is instantiated, we may not be able to do much more advanced things with it (I mean, setting up any unit testing that doesn’t require WordPress core is going to be impossible).

WP_Query Readability Improvements

This is the face of one who can’t follow your code.

With that said, here’s an example of how it can look when you start out and then how it can be refactored to have smaller functions each of which are more intentional than one long method.

An Example

For this post, let’s say I need to query the database for all published posts and posts and I want to order them by the ID.

Next, I want to determine if some third-party tool as assigned some metadata to it that corresponds to a template that I can later programmatically assign given a theme that I have.

Perhaps the initial version of the code might look something like this:

That’s a lot of code to do quite a bit of work for one function. At the very least, it lays out everything that needs to happen, doesn’t it?

Before reading any further, note the mapping array is just an example but the keys represent the meta key for mapping it, and that helps us to map defining the _wp_page_template value when it comes time to map it to actual WordPress template files.

So how can this be broken down?

1. Kick the Whole Thing Off

The first thing we want to do is create a function that sets the entire thing into motion. There are some ways that you can choose to do this.

Here’s how I’ve opted to do it:

Simply put, it will use a few helper functions – all of which I’ll document below – and then assign whatever templates we have in the mapping array defined above.

2. Load Posts and Pages

Naturally, the first thing we want to do is setup a function to call that will return use the results of the query:

This returns the results of the query. This way, we can determine if we need to do any additional work which we say in the gist in the previous step:

If not, then we’re done. Otherwise, obviously, we keep going.

3. Retrieve the Third-Party Template ID

Next, the idea of assigning templates – as shown in the code above – seems simple enough but there are a few things we need to do first:

  1. iterate through the posts,
  2. grab the third-party ID of the template,
  3. grab the third-party template name,
  4. assign the template from the mapping constant defined earlier in the class.

The initial iteration of the function may look like this:

But as you can see, there are still helper functions that need definitions. Things like the ability to get the template ID, the template name, and ultimately assign the template.

Note, however, that if any of the helper functions don’t return a useful value, then we continue with the loop. This is necessary if for not other reason than to make sure that we aren’t trying to map templates that don’t exist (but I find it also makes it a bit easier to read).

4. Find the File to Which the Template ID Maps

Next, a small function can be used to look at the third-party template ID and determine if we can map this value to the pages that exist in our database.

If it can’t, then we can return an empty string and then have the function that invoked this particular check to see if it’s worth continuing with the loop we’ve defined.

5. Grab the Template Name

Assuming that we have a valid post ID, now we need to retrieve the template name from the mapping array defined earlier in the post:

Here’s the thing: We’re either going to return the name of the template, or we’re going to return a null value. Again, this is so that we can determine if we need to continue with the loop of assigning templates or not.

6. Assign the Template

Finally, we can grab the ID of the template as provided by the third-party and use that to map to the file we have included with our work as outlined earlier in the post:

And that is ultimately how you can create much smaller, easier to read and easier to use code and functions when working with slightly more complicated queries.

And Thus, Readability Improvements

For those used to writing reading long methods or doing things in the way much of the tutorials on the web show how to do things in WordPress, this may look like a lot of pointless code.

But consider this:

  1. Longer methods are harder to read,
  2. They can be harder to debug,
  3. And they don’t break down the problem into more manageable pieces.

Sure, I’d love to break this down into even more classes with their responsibilities, and I believe it can be done, but given the nature of WP_Query, it would require a little more work.

So I’ve tried to strike as much middle ground as possible.

If you’re working with even slightly more advanced uses of WP_Query, then I recommend at least considering breaking it down into smaller pieces.

This helps to take care of readability, potentially any maintainability, and to write cleaner code rather than one long method with too many conditionals and reliance on a variety of other data.


  1. Mike Hemberger

    Nice approach. If going this route, where would the safest place for wp_reset_query() be?

    • Tom

      Since we’re using WP_Query, we really need to be using wp_get_postdata(). There are a few places that you may choose to place it, but I’ve opted to place it outside the loop. I’ve updated the gist in the three section to address this.

      Great question and thanks for bringing it up! :)

      • Mike Hemberger

        Thanks Tom. I’ve always wondered if we didn’t have posts, if we still need to reset it. If that were the case it would make more sense at the end of map_page_templates() method. I’ve been using WP_Query for years, but haven’t dove into what wp_reset_query() is actually doing/preventing/helping.

        • Ihor Vorotnov

          The wp_reset_query() function restores the value of global $wp_query to the original main query, in case you’ve modified it (the main query, usually with query_posts() or messing up with globals). The $wp_query contains not only found posts (0 or many), but the entire WP_Query object. So yes, if you’ve replaced or modified the main query, use this function to revert it back to main query.

          After restoring $wp_query it also calls wp_reset_postdata() function, which, in turn, restores the $post global variable to the current post in the main query. It should be used after custom WP_Query loops, because $posts->the_post() method in a custom loop replaces global post data with the data from current loop iteration. In the of the loop, the last post from that loop stays in globals. Calling wp_reset_postdata() after the custom loop brings back the post data from main loop back to globals.

          Hope it helps :)

          • Mike Hemberger

            Great info, thanks Ihor.

            Also, replying via email/postmatic for the first time. Wow, this is convenient!

Leave a Reply

© 2020 Tom McFarlin

Theme by Anders NorenUp ↑