Mar 03, 2016 UPDATED: Updated all routes in this post so now should be compatible with WP API V2 beta 12. Feb 28, 2016 UPDATED: Just realised since v2 beta 4,/posts
WP_Query
vars was moved back tofilter
param. I'll update all routes in this post ASAP.
In the post adding fields to the JSON response of the WP REST API, you’ve learned about how to manipulate the data from the WP REST API (WP-API). Another topic I got asked very often, is how to get posts by certain filters – mostly taxonomy and meta field. So today let’s talk about it.
Before we get started, if you’re looking for the workarounds for WP-API v1.x, Josh has written great tutorials for you. Here are the links of them:
In the following article, I’ll show you the quick answers and a more bigger picture beyond them. If you’re not interested in the later one, feel free to skip it.
The Quick Answers
*** Please note, starting from WP API v2 beta 4, you need to set "show_in_rest" => true
when registering a custom post type or taxonomy, to get it exposed to the JSON response. ***
So here are them. If you want to get posts by taxonomy with WP-API v2.0, you can use the endpoint/route like this: (job-type
is the taxonomy and manager
is the term you want to match)
wp-json/wp/v2/posts?filter[job-type]=manager
Please note if you set the query_var
to false
when registering the custom taxonomy, you’ll need to change the parameters to:
wp-json/wp/v2/posts/?filter[taxonomy]=job-type&filter[term]=manager
As to the default taxonomy – tag, the rule applies too:
wp-json/wp/v2/posts/?filter[tag]=love
But you need to be careful that with another default taxonomy – category, the parameter to use is categor_name
, so it’s like:
wp-json/wp/v2/posts/?filter[category_name]=uncategorized
Get Posts By Meta Field Is Not Available By Default
When it comes to meta fields, you might already know that this is not working with WP-API by default (for security reason). When using the terms “by default”, you must be very happy to expect a workaround to hack it. And almost everything magic in WordPress is related to a hook – action or filter, so which is to the rescue in this case?
That’s it: the rest_query_vars
filter. Here’s how to use it:
With the hook, now you can use the route below to query posts by meta:
wp-json/wp/v2/posts?filter[meta_key]=MY-KEY&filter[meta_value]=MY-VALUE
BTW, If you’re interested in getting custom post types worked with WP-API v2, please refer to the tips shared by @joneslloyd.
What about meta_query
for complex meta key/value pairs?
If you want to query posts based on multiple meta key/value pairs, you must use meta_query
to do so. As the example above, we also need to add it to the valid query variables, like this:
And then you can use meta_query
with WP API v2. I know some people stuck in how to write arrays as GET/POST parameters, since meta_query
is an array composited by arrays, which looks pretty scary when thinking of converting it to URL parameters for /posts
route in WP API.
Luckily I found MailChimp have documented it in their API docs, be sure to check it out!
What’s The Bigger Picture?
When I was a junior developer (around 2007 – 2008), one of the things bothered me most is when the library or code I was working with wasn’t well documented. To be honest, back to those days I could barely get the job done even when the documentation was thoroughly. For example, I couldn’t build a web application with Zend framework on my own, which was very well documented then as I recall.
Years went by luckily I developed a few problem solving skills on programming, one of them is to refer to the source code when I can’t get clear answers from the documentation.
The series of building themes with AngularJS and WP REST API was focus on the AngularJS in the first 14 posts. But then I realized I need to spend more time with WP REST API since sometimes the questions from my readers can be solved easily if they understand better how the WP-API or WP_Query works.
It’s all about the query_vars
So let’s take a look at a simple but powerful function from the source code of WP-API:
This get_allowed_query_vars
function is from the WP_REST_Posts_Controller
class, which is in charge of what query variables (that we pass to the route like category
and tag
) can be used to get posts with WP-API.
This function does the following jobs:
- Line 16: Get all valid query variables from
$wp->public_query_vars
. We’ll introduce what exactly they are later. - Line 18-33: If the user can
edit_posts
, she/he can access more query variables with$wp->private_query_vars
, we’ll also talk about them later. - Line 35: There are three more query variables added by WP-API:
posts_per_page
,ignore_sticky_posts
andpost_parent
- Line 47: At the end of this function, we can use the filter
rest_query_vars
to modify all the query variables available. For example we can add or remove variables here. (We just learned the trick minutes ago.)
The public and private query variables lists
There’s a page on the WordPress codex for this but it seems not quite completed, so let’s look into the source code again, but in WordPress itself this time.
Tracing to the wp-includes/class-wp.php
, you’ll see the two variables we’re looking for: $public_query_vars
and $private_query_vars
. Besides these variables when we register custom post types or taxonomies, if we set the query_var
to a string (can’t be empty string of course), it will be joined to the $public_query_vars
family.
Why posts_per_page Doesn’t Work (At Least In v2.0-beta3)
Now we know how many query variables are available. But after some tests I found a very interesting fact: the posts_per_page
parameter isn’t working.
I took another look at the source code of WP-API. From the same class (WP_REST_Posts_Controller
), the get_items
function helped me to figure that out:
At line 15 (from the gist above), you can see the WP-API actually gets posts_per_page
from another parameter called per_page
but not the posts_per_page
itself. I haven’t investigate every piece of code in WP-API so I can’t think of a good reason why it does so.
From this issue on the GitHub repo of WP-API, I think the developers are still working on the arguments style (see this comment). It’s a very informative discussion so be sure to check that out.
Improving The Security Of Meta Query When Working With WP-API v2.0
If you’ve kept an eye on WP-API for a while, you must notice that every time someone asks about the “meta query”, she/he will be reminded that “there might be some security risks” if exposing meta values to the WP-API.
I never store any confidential or sensitive data in post meta so I really hope things can be easier. But since WordPress and WP-API don’t work that way, let’s see what else we can do.
Limiting The Meta Keys Can Be Queried
No matter which filter you use to add the meta_key
and meta_value
to the $valid_vars
(you can use query_vars
, rest_private_query_vars
and rest_query_vars
), you basically allow all meta fields can be queried. If it’s too risky to you, try to limit the meta_key
to only allowed fields with rest_post_query
filter.
I hope you enjoy this post and would love to spend more time to know WP-API v2.0 better. If you encounter any question when following the steps from this tutorial, just shoot me an email: yoren [at] 1fix.io, or ping me on Twitter (@1fixdotio), and comments are much welcome. Talk soon!
Leave a Reply