{ title: "Building great things with the WP-API", date: "2015-08-28 14:00:53", venue: "WordCamp Norrköping 2015", author: "Christoffer Larsson, @chredd" }

(Some demo links removed due to local environments)

Building great things with the

WP-API

2015-08-28, WordCamp Norrköping

Who am I?

@chredd

WordPress REST API

API?

API: Application Programming Interface

http://en.wikipedia.org/wiki/Application_programming_interface

REST?

REST: REpresentational State Transfer

http://en.wikipedia.org/wiki/Representational_state_transfer

POST - GET - PUT - DELETE

Create - Read - Update - Delete

JSON?

JSON: JavaScript Object Notation

http://json.org/

The WP-API project

Access your site's data through an easy-to-use HTTP REST API

http://wptavern.com/ryan-mccue-on-creating-the-json-rest-api-for-wordpress

Version 2.0 beta

Development Only: Due to the lack of forwards and backwards compatibility, we strongly recommend you do not run the beta in production environments. While it is possible to run it (both security and privacy have solid, thorough handling), any updates will likely break your site.

- Ryan McCue 7:05am, on April 29, 2015

CRUD operations on

Posts Post meta Post revisions
Pages Media Comments
Taxonomies Terms Users

But why?

I'll tell you why!

What we built

And things we learned

Fetching data from WordPress (core)

Version 1.x:
https://yoursite.com/wp-json/

Version 2.0 beta:
https://yoursite.com/wp-json/wp/v2

Fetching data, example requests

Post data / Post data (Wired.com)

Posts using filters

Custom endpoint: Discovery block

Available endpoints (Wired.com)

List categories (Wired.com)

Modify post data (version 1.x)


add_filter( 'json_prepare_post', 'add_post_data', 10, 3 );

function add_post_data( $_post, $post, $context ) {
	$_post['post_title'] = 'Hello World';
	[...]
	return $_post;	
}
					

Add post data (version 2.0b)


// Add fields to posts
add_action( 'rest_api_init', 'post_register_random_info' );
function post_register_random_info() {
	register_api_field( 'post', // What api resource to target, post, page, user etc
		'random_info', // Name of field
		array(
			'get_callback'    => 'get_random_info', // Get callback
			'update_callback' => null, // Put callback
			'schema'          => null,
		)
	);
}

// Just return some random data
function get_random_info( $object, $field_name, $request ) {
	$data = array(
		'data' => md5( rand( 0, 100000 ) ),
	);

	return $data;
}
					

Demo

Modify post data (version 2.0b)


// Use this filter to filter output for posts.
// Change 'post' to whatever resource (user, media, comment, etc) to filter
add_filter( 'rest_prepare_post', 'remove_post_data', 10, 3 );

function remove_post_data( $data, $post, $request ) {
	unset( $data->data['sticky'] ); // Don't show this!

	return $data;
}
					

Modify any data (version 2.0b)

Modify author data (version 1.x)


add_filter( 'json_prepare_user', 'add_user_metadata', 10, 3 );

function add_user_metadata( $user_fields, $user, $context ) {
	add_author_meta_field( $user_fields, 'twitter' );
	[...]
	return $user_fields;
}

function add_author_meta_field( &$user_fields, $field ) {
	if ( $meta = get_the_author_meta( $field, $user_fields['ID'] ) ) {
		$user_fields[ $field ] = $meta;
	}
}
					

Add author data (version 2.0b)


// Add extra fields to user
add_action( 'rest_api_init', 'slug_register_user_info' );
function slug_register_user_info() {
	register_api_field( 'user', // What api resource to target, post, page, user etc
		'user_extra_info', // Name of field
		array(
			'get_callback'    => 'get_user_extra_info', // Get callback
			'update_callback' => null, // Put callback
			'schema'          => null,
		)
	);
}

// Callback for getting extra user info
function get_user_extra_info( $object, $field_name, $request ) {
	$data = array(
		'twitter'   => get_the_author_meta( 'twitter', $object['id'] ),
		'facebook'  => get_the_author_meta( 'facebook', $object['id'] ),
		'instagram' => get_the_author_meta( 'instagram', $object['id'] ),
	);

	return $data;
}
						
Demo

Removing endpoints (version 1.x)


add_filter( 'json_endpoints', 'filter_endpoints', 20, 1 );

function filter_endpoints( $endpoints ) {
	$disable_endpoints = array(
		'/taxonomies',
		'/media',
		'/pages',
		[...]
	);

	foreach ( $disable_endpoints as $disable ) {
		if ( isset( $endpoints[ $disable ] ) ) {
			unset( $endpoints[ $disable ] );
		}
	}

	return $endpoints;
}
						

Removing endpoints (version 2.0b)


// Filter endpoints, removing those not wanted
add_filter( 'rest_endpoints', 'filter_endpoints', 20, 1 );

function filter_endpoints( $endpoints ) {
	// Patterns available at the root of the api
	$disable_endpoints = array(
		'/wp/v2/media',
		'/wp/v2/media/(?P[\d]+)',
		'/wp/v2/comments',
		'/wp/v2/comments/(?P[\d]+)',
	);

	foreach ( $disable_endpoints as $disable ) {
		if ( isset( $endpoints[ $disable ] ) ) {
			unset( $endpoints[ $disable ] );
		}
	}

	return $endpoints;
}
						

Adding endpoints (version 1.x)


add_filter( 'json_endpoints', 'filter_endpoints', 20, 1 );

function filter_endpoints( $endpoints ) {
	
	$endpoints['/discovery'] = array(
		array( 'get_discovery', \WP_JSON_Server::READABLE ),
	);
	[...]

	return $endpoints;
}
					

Adding endpoints (version 2.0b)


// Register new route/endpoint
add_action( 'rest_api_init', function () {
	register_rest_route(
		'kit/v2', // Namespace for route/endpoint
		'/discovery', // Route to be used, can contain regexp
		array(
			'methods'  => 'GET', // Endpoint, get
			'callback' => 'kit_get_discovery', // Call this function
			'args'     => array(), // Optional args, validation etc
		)
	);
} );


function kit_get_discovery( $args = null ) {
	$posts = get_posts(
		array(
			'posts_per_page' => 1,
			'post_status'    => 'publish',
			'orderby'        => 'rand',
		)
	);
	$data  = array(
		'info'        => date( 'Ymdhis', time() ) . '/' . time(),
		'random_post' => $posts,
	);

	if ( empty( $posts ) ) {
		return new WP_Error( 'kit_no_posts', 'No posts available!', array( 'status' => 404 ) );
	}

	return new WP_REST_Response( $data, 200 );
}
					

Adding endpoints (version 2.0b)


// Register new route/endpoint
add_action( 'rest_api_init', function () {
	register_rest_route(
		'kit/v2', // Namespace for route/endpoint
		'/page/(?P[A-Za-z_-]+)', // Route to be used, can contain regexp
		array(
			'methods'  => 'GET', // Endpoint, get
			'callback' => 'kit_get_page', // Call this function
			'args'     => array(
				'slug' => array(
					'sanitize_callback' => 'sanitize_title'
				)
			), // Optional args, validation etc
		)
	);
} );


function kit_get_page( $request = null ) {
	$slug = $request->get_param( 'slug' );
	$post = get_posts(
		array(
			'name'        => $slug,
			'post_status' => 'publish',
			'post_type'   => 'page',
		)
	);

	// No post found, return wp_error for the api to handle
	if ( empty( $post ) ) {
		return new WP_Error( 'kit_no_page_found', 'Page not found!', array( 'status' => 404 ) );
	}

	$data = array(
		'title'   => $post[0]->post_title,
		'date'    => $post[0]->post_date,
		'content' => trim( $post[0]->post_content ),
		'author'  => get_the_author_meta( 'display_name', $post[0]->post_author ) . ', @' . get_the_author_meta( 'nickname', $post[0]->post_author ),
	);

	return new WP_REST_Response( $data, 200 );
}
					

Authentication

http://v2.wp-api.org/guide/authentication/

  • Cookies (WP themes and plugins)
  • Basic Auth (dev/staging)
  • OAuth1 (production)

Some other examples

How do I get started?

What's next?

More reading / resources

Questions?

@chredd

[email protected]