{"id":166679,"date":"2017-08-14T13:00:13","date_gmt":"2017-08-14T13:00:13","guid":{"rendered":"https:\/\/premium.wpmudev.org\/blog\/?p=166679"},"modified":"2022-04-11T03:45:57","modified_gmt":"2022-04-11T03:45:57","slug":"wp-query-arguments-filterable","status":"publish","type":"post","link":"https:\/\/wpmudev.com\/blog\/wp-query-arguments-filterable\/","title":{"rendered":"How to Make WP_Query Arguments Filterable"},"content":{"rendered":"<p>The <code>WP_Query<\/code> class is very powerful. It lets you create your own custom queries to run anywhere in your WordPress site \u2013 in the main content, in the sidebar or anywhere else you like.<\/p>\n<p>It&#8217;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&#8217;ve lost count of how many times I&#8217;ve coded a custom query using <code>WP_Query<\/code>.<\/p>\n<p>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.<\/p>\n<p>This won&#8217;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 <code>WP_Query<\/code> instance once and then tweak it when you need to.<\/p>\n<p>In this post, I&#8217;ll show you how to write a plugin with a filterable instance of <code>WP_Query<\/code> and then write a function in your theme&#8217;s functions file to edit the arguments.<\/p>\n<p>Continue reading, or jump ahead using these links:<\/p>\n<ul>\n<li><a href=\"#what-you-ll-need\">What You&#8217;ll Need<\/a><\/li>\n<li><a href=\"#writing-the-wp-query-plugin\">Writing the WP_Query Plugin<\/a><\/li>\n<li><a href=\"#adding-filterable-arguments\">Adding Filterable Arguments<\/a><\/li>\n<li><a href=\"#using-the-filter-in-your-theme\">Using the Filter in Your Theme<\/a><\/li>\n<li><a href=\"#filtering-the-arguments-in-your-theme\">Filtering the Arguments in Your Theme<\/a><\/li>\n<\/ul>\n<h2 id=\"what-you-ll-need\">What You&#8217;ll Need<\/h2>\n<p>To follow along with this post, you&#8217;ll need access to a couple of things:<\/p>\n<ul>\n<li>A development or testing installation of WordPress running your own theme or a child theme<\/li>\n<li>A code editor<\/li>\n<\/ul>\n<p>You&#8217;ll also need an understanding of <a href=\"https:\/\/wpmudev.com\/blog\/create-wordpress-plugin\/\" target=\"_blank\">how to write plugins<\/a>, <a href=\"https:\/\/wpmudev.com\/blog\/functions-file\/\" target=\"_blank\">how to edit the functions file<\/a>, and <a href=\"https:\/\/wpmudev.com\/blog\/mastering-wp-query\/\" target=\"_blank\">how <code>WP_Query<\/code> works<\/a>.<\/p>\n<p>Ready? Then let&#8217;s begin!<\/p>\n<h2 id=\"writing-the-wp-query-plugin\">Writing the WP_Query Plugin<\/h2>\n<p>Start by creating your plugin. Create a new folder for your plugin in your <em>wp-content\/plugins<\/em> 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.<\/p>\n<p>Here&#8217;s the opening lines of my plugin:<\/p>\n<p><span style=\"font-weight: 400;\"><div class=\"gist\" data-gist=\"f7a8457f0f7d9ce18ed552844154c459\" data-gist-file=\"plugin opener\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/f7a8457f0f7d9ce18ed552844154c459.js?file=plugin+opener\">Loading gist f7a8457f0f7d9ce18ed552844154c459<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div><\/span><\/p>\n<p>Now let&#8217;s add the <code>WP_Query<\/code> function. I&#8217;ll start by adding the <code>$args<\/code> variable, but keep it empty:<\/p>\n<p><span style=\"font-weight: 400;\"><div class=\"gist\" data-gist=\"ccb691e686950165c0a77f482d9e57ac\" data-gist-file=\"wp query argst 1\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/ccb691e686950165c0a77f482d9e57ac.js?file=wp+query+argst+1\">Loading gist ccb691e686950165c0a77f482d9e57ac<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div><\/span><\/p>\n<p>Then we add the loop:<\/p>\n<p><span style=\"font-weight: 400;\"><div class=\"gist\" data-gist=\"0608a911184ed07f924e72c9f818fc1c\" data-gist-file=\"loop 1\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/0608a911184ed07f924e72c9f818fc1c.js?file=loop+1\">Loading gist 0608a911184ed07f924e72c9f818fc1c<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div><\/span><\/p>\n<p>Here&#8217;s the full function:<\/p>\n<p><span style=\"font-weight: 400;\"><div class=\"gist\" data-gist=\"11029e8732bc60f7e1872e135ea5c409\" data-gist-file=\"function no filter\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/11029e8732bc60f7e1872e135ea5c409.js?file=function+no+filter\">Loading gist 11029e8732bc60f7e1872e135ea5c409<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div><\/span><\/p>\n<p>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.<\/p>\n<p>Right now though, it won&#8217;t output anything, as those arguments are empty. Let&#8217;s add some arguments but wrap them in a filter.<\/p>\n<h2 id=\"adding-filterable-arguments\">Adding Filterable Arguments<\/h2>\n<p>Take the <code>$args<\/code> section of your code and edit it to add some arguments.<\/p>\n<p>I&#8217;m just going to add an argument for <code>posts_per_page<\/code>, to limit the number of posts output. I won&#8217;t add any other arguments: this way the most recent five posts will be output. If you&#8217;d like, you can add some different arguments.<\/p>\n<p><span style=\"font-weight: 400;\"><div class=\"gist\" data-gist=\"bdfea8622c91f93423026b627e739479\" data-gist-file=\"args no filter\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/bdfea8622c91f93423026b627e739479.js?file=args+no+filter\">Loading gist bdfea8622c91f93423026b627e739479<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div><\/span><\/p>\n<p>So far, so straightforward. Now let&#8217;s enclose those arguments in a filter. Here&#8217;s the code:<\/p>\n<p><span style=\"font-weight: 400;\"><div class=\"gist\" data-gist=\"0c7c617cf86145e8d623d5cbeaebeb4f\" data-gist-file=\"args with filter\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/0c7c617cf86145e8d623d5cbeaebeb4f.js?file=args+with+filter\">Loading gist 0c7c617cf86145e8d623d5cbeaebeb4f<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div><\/span><\/p>\n<p>This wraps our single argument in a filter called\u00a0<code>wpmu_filterable_query<\/code>, which you can then hook into from another plugin, or from your theme, to amend those arguments.<\/p>\n<p>While we&#8217;re at it, let&#8217;s add a filter to that header inside the loop, as it&#8217;s a bit generic.<\/p>\n<p>Edit your loop so it includes a filter:<\/p>\n<p><span style=\"font-weight: 400;\"><div class=\"gist\" data-gist=\"90fae59c95017bba7e346b7d2ae589b0\" data-gist-file=\"loop head filter\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/90fae59c95017bba7e346b7d2ae589b0.js?file=loop+head+filter\">Loading gist 90fae59c95017bba7e346b7d2ae589b0<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div><\/span><\/p>\n<p>And that&#8217;s it. Unless you decide to add some more filters to the loop, your plugin is ready.<\/p>\n<h2 id=\"using-the-filter-in-your-theme\">Using the Filter in Your Theme<\/h2>\n<p>The next step is to write a couple of functions in your theme.<\/p>\n<p>The first will call the <code>wpmu_filterable_query<\/code> action hook and output it in your page. You can call this in one of a number of ways.<\/p>\n<p>The first is to attach it to an action hook in your theme, by using the <code>add_action<\/code> function. So if your theme had a hook called <code>my_theme_sidebar_hook<\/code>, you would output the query in the sidebar like this:<\/p>\n<p><span style=\"font-weight: 400;\"><div class=\"gist\" data-gist=\"9b2c07651cb046f525b252f307a996d9\" data-gist-file=\"add action\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/9b2c07651cb046f525b252f307a996d9.js?file=add+action\">Loading gist 9b2c07651cb046f525b252f307a996d9<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div><\/span><\/p>\n<p>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&#8217;t have any hooks this might be the best approach. If you&#8217;re working with a third party theme, don&#8217;t edit the theme files directly &#8211; instead, create a copy of it in a child theme.<\/p>\n<p>Then in your theme template file, add a call to the\u00a0<code>wpmu_filterable_query<\/code> function:<\/p>\n<p><span style=\"font-weight: 400;\"><!-- Missing Gist ID -->fc1ae672a2dd8247f003e37ba79dd380\/gist]<\/span><\/p>\n<p>This simply runs the function in the spot in your template file where you place it.<\/p>\n<p>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&#8217;d make a copy of <em>page.php<\/em> from your theme or your parent theme, and replace the standard loop with the call to the function, as above.<\/p>\n<p>So that&#8217;s how you add the function to your theme. But how about filtering those arguments?<\/p>\n<h2 id=\"filtering-the-arguments-in-your-theme\">Filtering the Arguments in Your Theme<\/h2>\n<p>The final step is to write a function in your theme&#8217;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.<\/p>\n<p>Note that you could do this using a plugin if you wanted, but as you&#8217;ve already coded the function into your theme, I think it&#8217;s neater to add this code to your functions file.<\/p>\n<p>Let&#8217;s imagine you&#8217;ve registered a post type called <em>doohickey<\/em>, and you want to output that instead. But instead of outputting six posts, you want to show four.<\/p>\n<p>In your functions file, you&#8217;d need this code:<\/p>\n<p><span style=\"font-weight: 400;\"><!-- Missing Gist ID -->1ddc05a7ef7dc2f8cbd3e1c5d7f96677\/gist]<\/span><\/p>\n<p>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&#8217;ll have to add them to this function, as the new code overrides the old code, and doesn&#8217;t add to it.<\/p>\n<p>Next let&#8217;s add a function to edit the heading text:<\/p>\n<p><span style=\"font-weight: 400;\"><!-- Missing Gist ID -->a58a36ccf85713759e82b89797ef4962\/gist]<\/span><\/p>\n<p>That will output the content of the new function instead of <code>&lt;h3&gt;Heading&lt;\/h3&gt;<\/code>, which was inside the filter.<\/p>\n<p>You can amend both of these functions as you see fit.<\/p>\n<h2>Making WP_Query Filterable Makes Your Code More Efficient and Saves Time<\/h2>\n<p>If you&#8217;re going to be using the <code>WP_Query<\/code> class in lots of sites and want to save yourself the bother of coding <code>WP_Query<\/code> in full every time, this can save you some work. In each site where you use <code>WP_Query<\/code>, you only need to add the call for the function, and the function to attach to the filter hook.<\/p>\n<p>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 <code>include_once()<\/code> 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.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The WP_Query class is very powerful. It lets you create your own custom queries to run anywhere in your WordPress site \u2013 in the main content, in the sidebar or anywhere else you like. It&#8217;s something I use a lot, either in custom template files or in areas outside the content such as the sidebar [&hellip;]<\/p>\n","protected":false},"author":347011,"featured_media":167097,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"blog_reading_time":"","wds_primary_category":0,"wds_primary_tutorials_categories":0,"footnotes":""},"categories":[557],"tags":[10743],"tutorials_categories":[],"class_list":["post-166679","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development","tag-wp_query"],"_links":{"self":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/166679","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/users\/347011"}],"replies":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/comments?post=166679"}],"version-history":[{"count":13,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/166679\/revisions"}],"predecessor-version":[{"id":208194,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/166679\/revisions\/208194"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media\/167097"}],"wp:attachment":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media?parent=166679"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/categories?post=166679"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tags?post=166679"},{"taxonomy":"tutorials_categories","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tutorials_categories?post=166679"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}