How to Make WP_Query Arguments Filterable

Development

Finding yourself doing a lot of rework coding custom queries using WP_Query? Here’s how to automate it.

Developer's mind

The WP_Query class is very powerful. It lets you create your own custom queries to run anywhere in your WordPress site – in the main content, in the sidebar or anywhere else you like.

It’s something I use a lot, either in custom template files or in areas outside the content such as the sidebar or footer. And I’ve lost count of how many times I’ve coded a custom query using WP_Query.

But it is possible to avoid all that rework. If you make your query arguments filterable, you can write a function to amend the arguments and run a different query in different places in your site. This means you can write a plugin with some default arguments (or indeed with no arguments at all), and then write a function in your theme (or in another plugin) that amends those arguments.

This won’t change the loop that runs using your query arguments (although if you want you could also create another filter for that), but it does mean you can code your WP_Query instance once and then tweak it when you need to.

In this post, I’ll show you how to write a plugin with a filterable instance of WP_Query and then write a function in your theme’s functions file to edit the arguments.

Continue reading, or jump ahead using these links:

What You’ll Need

To follow along with this post, you’ll need access to a couple of things:

  • A development or testing installation of WordPress running your own theme or a child theme
  • A code editor

You’ll also need an understanding of how to write plugins, how to edit the functions file, and how WP_Query works.

Ready? Then let’s begin!

Writing the WP_Query Plugin

Start by creating your plugin. Create a new folder for your plugin in your wp-content/plugins folder, and then create a blank file inside that. I always create a folder in case I want to add any styles, scripts or include files to my plugin at a later date.

Here’s the opening lines of my plugin:

Loading gist f7a8457f0f7d9ce18ed552844154c459

Now let’s add the WP_Query function. I’ll start by adding the $args variable, but keep it empty:

Loading gist ccb691e686950165c0a77f482d9e57ac

Then we add the loop:

Loading gist 0608a911184ed07f924e72c9f818fc1c

Here’s the full function:

Loading gist 11029e8732bc60f7e1872e135ea5c409

We now have a fairly standard query and loop. This will run a query based on the arguments (which are currently empty), then output a heading followed by a list of the items fetched with links to them. It could be used to output a list of posts using categories, taxonomies, post types or anything else as the arguments.

Right now though, it won’t output anything, as those arguments are empty. Let’s add some arguments but wrap them in a filter.

Adding Filterable Arguments

Take the $args section of your code and edit it to add some arguments.

I’m just going to add an argument for posts_per_page, to limit the number of posts output. I won’t add any other arguments: this way the most recent five posts will be output. If you’d like, you can add some different arguments.

Loading gist bdfea8622c91f93423026b627e739479

So far, so straightforward. Now let’s enclose those arguments in a filter. Here’s the code:

Loading gist 0c7c617cf86145e8d623d5cbeaebeb4f

This wraps our single argument in a filter called wpmu_filterable_query, which you can then hook into from another plugin, or from your theme, to amend those arguments.

While we’re at it, let’s add a filter to that header inside the loop, as it’s a bit generic.

Edit your loop so it includes a filter:

Loading gist 90fae59c95017bba7e346b7d2ae589b0

And that’s it. Unless you decide to add some more filters to the loop, your plugin is ready.

Using the Filter in Your Theme

The next step is to write a couple of functions in your theme.

The first will call the wpmu_filterable_query action hook and output it in your page. You can call this in one of a number of ways.

The first is to attach it to an action hook in your theme, by using the add_action function. So if your theme had a hook called my_theme_sidebar_hook, you would output the query in the sidebar like this:

Loading gist 9b2c07651cb046f525b252f307a996d9

The second is to code it directly into a theme template file. I prefer to work with hooks where possible, as they give me more flexibility, but if your theme doesn’t have any hooks this might be the best approach. If you’re working with a third party theme, don’t edit the theme files directly – instead, create a copy of it in a child theme.

Then in your theme template file, add a call to the wpmu_filterable_query function:

fc1ae672a2dd8247f003e37ba79dd380/gist]

This simply runs the function in the spot in your template file where you place it.

The third option is to create a new template file, such as a page template file, which will run this query instead of the default query. In this case you’d make a copy of page.php from your theme or your parent theme, and replace the standard loop with the call to the function, as above.

So that’s how you add the function to your theme. But how about filtering those arguments?

Filtering the Arguments in Your Theme

The final step is to write a function in your theme’s functions file to filter the query arguments. You can also add a second function to filter the heading, as well as any functions to make use of any other filters you might choose to add to the loop in your plugin.

Note that you could do this using a plugin if you wanted, but as you’ve already coded the function into your theme, I think it’s neater to add this code to your functions file.

Let’s imagine you’ve registered a post type called doohickey, and you want to output that instead. But instead of outputting six posts, you want to show four.

In your functions file, you’d need this code:

1ddc05a7ef7dc2f8cbd3e1c5d7f96677/gist]

This replaces the contents of the original filter with the new contents in the function. Note that if you want to retain any of the arguments in the original filter, you’ll have to add them to this function, as the new code overrides the old code, and doesn’t add to it.

Next let’s add a function to edit the heading text:

a58a36ccf85713759e82b89797ef4962/gist]

That will output the content of the new function instead of <h3>Heading</h3>, which was inside the filter.

You can amend both of these functions as you see fit.

Making WP_Query Filterable Makes Your Code More Efficient and Saves Time

If you’re going to be using the WP_Query class in lots of sites and want to save yourself the bother of coding WP_Query in full every time, this can save you some work. In each site where you use WP_Query, you only need to add the call for the function, and the function to attach to the filter hook.

If you wanted to make your plugin even more flexible, you could use an include file for the loop instead of coding it directly into the plugin, and then enclose the include_once() call in a filter. This way, you could call a different include file if you wanted to, and output a different version of the loop.

All the good WordPress stuff, once every two weeks

Subscribe

Leave a comment