The WordPress REST API: �A Development Primer
Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Hi, I’m Andrew
Agency and Community Engineer at Pantheon.
ataylorme on GitHub and Twitter.
Some things I enjoy, aside from coding, are
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
In The Real World
@ataylorme • Slides: goo.gl/pQcFZK
WAMU.org
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Of Hoops & Healing / Bostonia
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Should I Use The REST API?
@ataylorme • Slides: goo.gl/pQcFZK
Opportunities
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Challenges
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Routes and Endpoints
@ataylorme • Slides: goo.gl/pQcFZK
REST API Terms
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
REST API Terms
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
REST API Terms
/wp-json/wp/v2/posts
Index
Namespace
Choose the endpoint by using different HTTP requests.�For example, GET to list posts and POST to create a new post.
Route
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Default Routes
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Default Routes Example
Routes and endpoints are discoverable at /wp-json
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Default Routes Example
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Routes For Custom Post Types
$args = array(� 'labels' => array(� 'name' => _x( 'Books', 'post type general name' ),� 'singular_name' => _x( 'Book', 'post type singular name' ),� ),� 'description' => '',� 'hierarchical' => false,� 'menu_position' => null,� // No admin UI or archive pages� 'public' => false,� // Expose through REST API� 'show_in_rest' => true,� 'rest_base' => 'books',� 'capability_type' => 'post',� 'supports' => array( 'title', 'editor', 'custom-fields' )� );� register_post_type( 'books', $args );
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Modifying Responses
register_rest_field(� 'books',� 'rating',� array(� 'get_callback' => function ( $data ) {� return (int) get_post_meta( $data['id'], '_book_rating', true );� },� 'update_callback' => function ( $value, $post ) {� $value = intval( $value );� if( $value >= 0 && $value <= 5){� update_post_meta( $post->ID, '_book_rating', $value );� }� },� 'schema' => array(� 'description' => __( 'The rating, 0 - 5, for the book.' ),� 'type' => 'integer'� ),� )�);
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Modifying Responses
Modified response for /wp-json/wp/v2/books
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Removing Items
function books_rest_prepare( $data, $post, $request ) {� $_data = $data->data;
� $unused_keys = array(� 'date_gmt',� 'modified_gmt',� 'template',� );�� foreach ( $unused_keys as $unused_key ) {� if ( isset( $_data[ $unused_key ] ) ) {� unset( $_data[ $unused_key ] );� }� }�� $data->data = $_data;�� return $data;�}��add_filter( 'rest_prepare_books', 'books_rest_prepare', 10, 3 );
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Removing Items
Modified response for /wp-json/wp/v2/books
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
WP-Notebook Example
K. Adam White of Bocoup presented about the WordPress REST API during LoopConf. �If you missed it check out the recording.
He created an example app as a companion to the talk and it's a great example using a custom post type in the REST API with a React front-end. Check it out on GitHub.
K. Adam also released wpapi - an isomorphic JavaScript client for interacting with the WordPress REST API. If you are using JavaScript to parse the WordPress REST API I encourage you to check it out.
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Custom Routes
@ataylorme • Slides: goo.gl/pQcFZK
Registering Routes
function register_books_rest_routes() {�� register_rest_route( 'app/v1', '/books, array(� 'methods' => 'GET',� 'callback' => 'list_books',� 'args' => array(),� ) );
�}��add_action( 'rest_api_init', 'register_books_rest_routes' );
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Registering Routes
function register_book_details_rest_route() {
register_rest_route( ''app/v1', '/books/(?P<id>\d+)', array(� 'methods' => 'GET',� 'callback' => 'book_details',� 'args' => array(� 'id' => array(� 'validate_callback' => function ( $param, $request, $key ) {� return ( false !== get_post_status( (int) $param ) );� }� ),� ),� ) );��}��add_action( 'rest_api_init', 'register_book_details_rest_route );
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Registering Routes
'validate_callback' => function ( $param, $request, $key ) {� if( ! is_numeric( $param ) ){� return new WP_Error(� 'books_bad_post_id',� __( 'Invalid post ID format. Please pass an integer.' ),� array( 'status' => 400 )� );� }� $post_id = (int) $param;� if ( false === get_post_status( $post_id ) || 'books' !== get_post_type( $post_id ) ) {� return new WP_Error(� 'books_bad_post_id',� __( 'Invalid books post ID.' ),� array( 'status' => 400 )� );� }� return true;�}
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Callback Methods
list_books callback method
book_details callback method
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Custom Routes
Response for /wp-json/app/v1/books
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Custom Routes
Response for /wp-json/app/v1/books/4
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Testing
@ataylorme • Slides: goo.gl/pQcFZK
Why: Security
@ataylorme • Slides: goo.gl/pQcFZK
Why: Reliability
@ataylorme • Slides: goo.gl/pQcFZK
1. Use the PHPUnit test suite
Run wp scaffold plugin-tests or wp scaffold theme-tests to add the following files to your project:
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
2. Create Your First Test
Create a class Test_REST_API in tests/test-rest-api.php with:
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
3. Test Endpoints Thoroughly
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Resources
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Keep in touch!
@ataylorme • Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK
Questions?
Slides: goo.gl/pQcFZK
@ataylorme • Slides: goo.gl/pQcFZK