Customizing WordPress API data

What i want:

  • remove unnecessary data from the response (e.g. _links)
  • add data from multiple endpoints to one response so that i don’t have to call multiple endpoints (e.g. featured image size URLs)
  • customize the data that is sent back (e.g. excerpts)

Notes:

  • The complete REST response is filtered through rest_prepare_post filter. It allows modification of the post type data right before it is returned.
  • Action hooks look like this: do_action( "hook_name" )
  • Filter hooks look like this: apply_filters( "hook_name", "what_to_filter" ).

add_filter

Hooks a function or method to a specific filter action.

// add_filter parameter
add_filter( string $tag, callable $function_to_add, int $priority = 10, int $accepted_args = 1 )

Examples

// Add Featured Image source URLs to the `/posts/` endpoint response

function add_featured_image_url ($data, $post, $context) {
	$featured_image_id = $data -> data['featured_media']; // get featured image ID from $data
	$featured_image_url = wp_get_attachment_image_src( $featured_image_id, 'original' ); // get URL of original size
	$featured_image_url_thumbnail = image_get_intermediate_size( $featured_image_id, 'thumbnail' ); // get URL of thumbnail size
	$featured_image_url_medium = image_get_intermediate_size( $featured_image_id, 'medium' ); // get URL of medium size

	if ( $featured_image_url_thumbnail ) {
		$data -> data['featured_image_url']['thumbnail'] = $featured_image_url_thumbnail['url'];
	}

	if ( $featured_image_url_medium ) {
		$data -> data['featured_image_url']['medium'] = $featured_image_url_medium['url'];
	}

	if ( $featured_image_url ) {
		$data -> data['featured_image_url']['full'] = $featured_image_url[0];
	}

	return $data;
}

add_filter( 'rest_prepare_post', 'add_featured_image_url', 10, 3); // 10 is priority and 3 is accepted_args. Both are optional

this will give us the following in the /posts/ endpoint results

featured_image_url: {
	thumbnail: "https://news.mydomain.net/wp-content/uploads/images/myimage-150x150.jpg",
	medium: "https://news.mydomain.net/wp-content/uploads/images/myimage-300x200.jpg",
	full: "https://news.mydomain.net/wp-content/uploads/images/myimage.jpg"
},
  • $data here is the entire default JSON response
  • the wp_get_attachment_image_src function gets the URL of any attachment image by taking its ID. Accepts any valid image size (e.g. ‘original’, ‘thumbnail’ 150x150, ‘medium’ 300x200, ‘full’ etc.). The first item in the returned array is the URL of the attachment image src..
  • image_get_intermediate_size gets the image source URL by taking the attachment ID and the image size.
  • Standard image sizes are: thumbnail, medium, medium_large, large.

Add Comment count

// Add comment count to the API response
function add_comment_count($data, $post, $context) {
	$args = array(
		'post_id' => $post -> ID, // Limit results affiliated with this post ID. Default 0.
		'count' => true, // return only the count, not an array of comment objects
		'status' => 'approve'
	);
	$comments = get_comments( $args );

	$data -> data['comment_count'] = $comments;

	return $data;
}

add_filter( 'rest_prepare_post', 'add_comment_count', 10, 3);
  • $data is the entire array of posts returned (default: 10)
  • $post is the individual post in that array
ID: 3347,
post_author: "1",
post_date: "2019-05-24 15:29:47",
post_date_gmt: "2019-05-24 15:29:47",
post_content: "This is post content. Blah blah blah",
post_excerpt: "This is the post excerpt. More blah.. ",
post_status: "publish",
comment_status: "open",
ping_status: "closed",
post_password: "",
post_name: "this-be-the-post-slug",
to_ping: "",
pinged: "",
post_modified: "2019-06-18 07:21:50",
post_modified_gmt: "2019-06-18 07:21:50",
post_content_filtered: "",
post_parent: 0,
guid: "https://news.mydomain.net/p=?3347",
menu_order: 0,
post_type: "post",
post_mime_type: "",
comment_count: "8",
filter: "raw"

Customize the excerpt

Precisely, remove the read more link as it goes to the wrong URL. Remove the continue reading link from auto generated excerpts by defining our own custom excerpt if one hasn’t been added by user

// Custom Excerpt
// Remove the continue reading link from auto generated excerpts by defining our own custom excerpt if one hasn't been added by user
function custom_excerpt ($data, $post, $context) {

	// unset( $data -> data['excerpt'] ); // remove the excerpt field (if you want to overwrite the default 'excerpt' response sent by the API)

	$content = $post -> post_content;
	$more = ' ... ';

	if ( ! has_excerpt($post -> ID)) {
		// This post does not has a user defined excerpt
		$data -> data['excerpt']['raw'] = wp_trim_words( $content, 55 , $more );
	}
	return $data;
}

add_filter( 'rest_prepare_post', 'custom_excerpt', 10, 3);
  • has_excerpt() takes a post ID and returns true/false depending on whether a custom user-defined excerpt was added for the post.

Troubleshooting

See values in \$post

function whothis ($data, $post, $context) {
	$whothis = $post;
	$data -> data['whothis'] = $whothis;
	return $data;
}
add_filter( 'rest_prepare_post', 'whothis', 10, 3);