AngularJS + WordPress Part 1: WordPress REST API

WordPress on it’s own does not have an API, something I find a bit strange.  Luckily for us, a plugin has already solved this problem for us, it just needs a little customization.

REST API Plugin

You want this one:
Screen Shot 2015-08-27 at 1.29.59 PM

With the plugin installed and activated, you should be able to visit your WordPress site’s URL plus “/wp-json/posts” (a la www.yoursite.com/wp-json/posts), and get back a full listing of all of your posts.  If you see this, great, the plugin is working, but you should immediately notice a problem.

This returns all data for all posts.  This is almost certainly more information than you would ever display to a user at one time, so let’s not return it all at once.  The first and most immediately obvious thing to do is to add pagination.  Even if you want to do an ‘infinite scroll’ style page, you still only want to load x posts at one time.

Pagination

To paginate, simply send the query string: “?filter[posts_per_page]=X&page=Y”, where X is the number of posts you want per page, and Y is the page you want. Following our old example url, “www.yoursite.com/wp-json/posts?filter[posts_per_page]=10&page=1” would return your first ten blog entries.

Returning Only Used Values

For the style of blog listing I’m doing, there’s another problem.  We’re getting all data for our paginated posts.  Now, if you want to show your full entries to the user on the blog listing page, this is a non issue for you.  If you look at my listing page however, you will notice I only show the title, the date, the featured image, and the excerpt.

So, I don’t want to return the actual content of my blog post, or any of the other fields present in that JSON that I don’t display.  This is not a feature of the REST plugin, so we need to do some customization.  Not being a WordPress or even a PHP developer, I did some googling.  Much searching led me to an example implementation by another developer, and that combined with reading some WordPress docs led me to a solution.

Customizing the Plugin

We’ll be editing json-rest-api plugin, specifically the plugin.php file.  You can do this by going to ‘Plugins’ on your WordPress admin view, finding WP REST APIclicking ‘Edit’, and finding ‘plugin.php’.  Here’s the code, which you can simply add to the end of the file:


add_filter( 'json_prepare_post', 'json_rest_api_filter_fields_post', 10, 3 );
function json_rest_api_filter_fields_post( $data, $post, $context ) {
	if ( !empty($_GET['fields']) )
	{
		$new_data = array();
		$fields = explode(',', $_GET['fields']);
		if ( empty($fields) || count($fields)==0 ) { return $data; }
		foreach ($data as $key => $value) {
			if (in_array($key, $fields)){$new_data[$key] = $value;}
		}
	}

	if ( !empty($_GET['custom_fields']) ) {
		$custom_fields = explode(',', $_GET['custom_fields']);
		foreach($custom_fields as $value) {
			$new_data[$value] = get_post_meta($new_data['ID'], $value, true);
		}	
	}
	return isset($new_data) ? $new_data : $data;
}

While I’m not a PHP developer, in context it’s easy to see what’s going on here.  The params are checked for “fields”, and if that param has been passed in, the value is separated into an array on each comma. Provided there is at least one field in this array, loop through the data being returned and populate a new array with just the keys passed in in the fields param.

With that knowledge and some reading in the WordPress documentation, I added the next section which adds any custom fields to the data that were passed in the “custom_fields” param.

Now you can specify the fields you want to display and you can also add any custom fields you might want to show by simply adding the query string “?fields=X,Y,Z&custom_field=A,B,C”, where X, Y, and Z are the JSON key names, and A, B, and C are the names of any custom fields you have added.  So to only show the title and excerpt for your first page of entries the entire url would look like “www.yoursite.com/wp-json/posts?filter[posts_per_page]=10&page=1&fields=title,excerpt”.

And that’s it for now, we’re ready to use the API in our Angular app.