Making WordPress REST API Calls Internally

Making WordPress REST API Calls Internally

The WordPress REST API is great for gaining access to your data from external sites or from front-end JavaScript applications. It is even great for one-off calls you probably used to make via normal WordPress AJAX. However, have you ever wanted or needed to make WordPress REST API calls internally?

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.

Why?

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.

My particular use case for needing this was that I wanted to avoid making an initial HTTP request to fetch the initial data for a JavaScript application. While I could have the JavaScript application make an HTTP request as soon as it loaded, there were a few reasons why an internal REST API call would make more sense:

    1. 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.
    2. 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.
    3. 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.

<?php

$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 wp_json_encode() function.

So what do you think? Have you done anything like this before? If so, I’d love to hear more about your use case!

Advertisements
  1. Thanks, this helped a me a lot! We use our API with JavaScript for the most part, but a scenario came up where it was preferable to consume the data with PHP.

  2. Thank you much much! Been searching for something like this for a while now.

    I’ve been creating serializer/transformer classes that transform each post type into something that matches the API’s JSON structure, but haven’t felt good about it, especially since I use `node-wpapi` for requests after the initial page load. I’d attempted to use the REST controllers’ `prepare_item_for_response` function and a few other shots, but to no avail. Things like `acf-to-rest-api` weren’t called.

    I’m using this for the same reasons as you: __INITIAL_DATA__ to avoid the extra HTTP request (for a Vue application in my case). And for the consistent object structure.

    Just gave this code a quick spin, and it’s working perfectly. The `acf-to-rest-api` and `better featured image` hooks work as they would from an actual REST request.

    The only complaint I have about an internal request is that I’m still limited to `per_page <= 100` per request… sure would be nice if internally I could up that one, but it's still easy enough to handle.

  3. Thank you, Micah.

    I am planning to do something very similar and your article helped greatly. The same “why would I do this?” thoughts came to my mind and I am glad I am not alone 🙂

    Anton

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.