The WP API is quite handy, but in some cases requires a lot of customization to get what we really need out of it. The post schema offers us most of what we can usually get out of the WP_Query class, but lacks one specific field that many of us use a lot – the post excerpt. So for a simple example, we can use register_rest_route() to add it in.
We start off with the usual – hook into rest_api_init:
add_action( 'rest_api_init', 'register_api_hooks' ); function register_api_hooks() { $postObjects = [ 'post', 'portfolio' ]; register_rest_field( $postObjects, 'post_excerpt', [ 'get_callback' => 'rest_field_excerpt' ]); }
Note the first line of our function:
$postObjects = [ 'post', 'portfolio' ];
The first argument of register_rest_field() accepts a string or “mixed”, object/array of post types. This line is setting up an imaginary “portfolio” custom post type to be given any new fields along with the usual “post”. This makes it easy to apply our changes to any post type.
I usually like to use closures for hooks like these so we don’t clutter our code with what seem like arbitrary functions at first glance. They are also still in the global scope, as this would be if dropped into the functions.php file. Closures are usually cleaner – e.g.:
add_action( 'rest_api_init', function() { // code here });
However this makes it virtually impossible to add filters later on, as we don’t have a named function to refer to. More on this in a later post. Here is our callback:
function rest_field_excerpt( $object, $fieldname, $request ) { return strip_tags( html_entity_decode( get_the_excerpt( $object['id'] ) ) ); }
The $object parameter is the post, so we can access whatever appears within the WP_Post object as an array index. The two additional parameters are optional, they’re shown here just to show they can be used.
So now we have a new field available, named post_excerpt via the second argument in register_rest_field(). We’re stripping out the HTML and decoding any unwanted entities.