What do I mean? I mean being able to make a WordPress REST API call directly within PHP without making an HTTP request. Of course, this would only work if you want the data out of the site on which your code is running.
You are probably thinking, isn’t this what
WP_Query is for? Why use an internal REST API call to do something that WordPress already allows you to do? Well, the main reason is because
WP_Query returns data in a completely different format than the REST API.
- I could avoid the HTTP request altogether by making an internal query and passing the initial data to the app directly from PHP. This would make my application load much faster.
- I could avoid the lag where a user sees the initial state of the application with no data until the initial HTTP request completes. This would make my application not only be faster but also provide a better user experience. There would be no need for initial loading graphics, time to interaction would be less, etc.
- In the event that users don’t actually interact with the application, no additional HTTP requests are made to the web server. If we made the extra HTTP request, we would end up loading WordPress and all the plugins twice as opposed to just once. Depending on our application’s bounce rate, this could significantly affect the load on the web server.
How to Make an Internal WordPress REST API Call
It isn’t difficult to make an internal REST API call, but it is a bit more involved than your normal
WP_Query usage. Also, keep in mind that the parameters you pass to the REST API are not always the same as what you would pass to
WP_Query. For example, the
post_status query var would become
status when making an API request.
$request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
$request->set_query_params( [ 'per_page' => 12 ] );
$response = rest_do_request( $request );
$server = rest_get_server();
$data = $server->response_to_data( $response, false );
$json = wp_json_encode( $data );
Basically, you will start by creating a new instance of a
WP_REST_Request. This takes two parameters: the method and the route. Since you will most likely only be querying data, you’ll probably only use the
GET method for internal requests although you could make
POST requests as well.
Once you have a request, you can call the
set_query_params() method to pass any arguments that you would normally have set in the URL query string. You can set headers as well, but it is important to note that authentication isn’t performed when making internal requests. As such, you will want to make sure that normally protected endpoints aren’t exposed by using this method. Be sure to add any applicable capability checks.
Once you’ve set up your request object, just pass it to the
rest_do_request() function to get a response object.
Finally, get an instance of the REST server by calling
rest_get_server(). Then call the
response_to_data() method on the server and pass it your response object. The second parameter is the
embed option. If false, things like authors and featured images won’t be embedded in the data. If true, they will be embedded. What is returned by doing this is an array containing the data you would normally get in JSON format from the REST API. All you need to do to get actual JSON is to run the data returned through the
So what do you think? Have you done anything like this before? If so, I’d love to hear more about your use case!