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:
- Define the arguments,
- Instantiate WP_Query,
- Check if there are posts,
- Loop through them,
- 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).
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.
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:
- iterate through the posts,
- grab the third-party ID of the template,
- grab the third-party template name,
- 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:
- Longer methods are harder to read,
- They can be harder to debug,
- 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.