Skip to content

Instantly share code, notes, and snippets.

@ataylorme
Last active April 17, 2024 17:27
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ataylorme/5238f2bf710c90fd9b5baa172b712edf to your computer and use it in GitHub Desktop.
Save ataylorme/5238f2bf710c90fd9b5baa172b712edf to your computer and use it in GitHub Desktop.
Books WordPress REST API Example
<?php
function register_books_cpt() {
$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' => true,
// 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 );
}
add_action( 'init', 'register_books_cpt' );
function add_book_info_metabox() {
add_meta_box( 'book-info-meta-box', 'Book Info', 'book_info_metabox_markup', 'books', 'advanced', 'high', null );
}
add_action( 'add_meta_boxes', 'add_book_info_metabox' );
function book_info_metabox_markup( $object ) {
wp_nonce_field( basename( __FILE__ ), 'book-info-meta-box-nonce' );
?>
<div>
<label for='_book_rating'>Book Rating</label>
<select name='_book_rating'>
<?php
$option_values = array( 0, 1, 2, 3, 4, 5 );
foreach ( $option_values as $key => $value ) {
if ( $value == get_post_meta( $object->ID, '_book_rating', true ) ) {
?>
<option selected><?php echo $value; ?></option>
<?php
} else {
?>
<option><?php echo $value; ?></option>
<?php
}
}
?>
</select>
</div>
<?php
}
function save_book_info_metabox( $post_id, $post, $update ) {
if ( ! isset( $_POST['book-info-meta-box-nonce'] ) || ! wp_verify_nonce( $_POST['book-info-meta-box-nonce'], basename( __FILE__ ) ) ) {
return $post_id;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
if ( 'books' != $post->post_type ) {
return $post_id;
}
$book_rating = '';
if ( isset( $_POST['_book_rating'] ) ) {
$book_rating = (int) $_POST['_book_rating'];
}
update_post_meta( $post_id, '_book_rating', $book_rating );
}
add_action( 'save_post', 'save_book_info_metabox', 10, 3 );
<?php
function book_details( $request ) {
$post_id = (int) $request['id'];
$rating = get_post_meta( $post_id, '_book_rating', true );
$rating = ( empty( $rating ) ) ? false : (int) $rating;
$thumbnail = get_post_thumbnail_id( $post_id );
if ( empty( $thumbnail ) ) {
$thumbnail = false;
} else {
$thumbnail = wp_get_attachment_image_src( $thumbnail, 'thumbnail' );
if ( is_array( $thumbnail ) ) {
$thumbnail = array(
'src' => $thumbnail[0],
'width' => $thumbnail[1],
'height' => $thumbnail[2],
);
}
}
global $post;
$post = get_post( $post_id );
setup_postdata( $post );
if ( null !== $post ) {
$return = array(
'ID' => $post_id,
'title' => get_the_title(),
'thumbnail' => $thumbnail,
'rating' => $rating,
'content' => get_the_content(),
);
wp_reset_postdata( $post );
}
$response = new WP_REST_Response( $return );
$response->header( 'Access-Control-Allow-Origin', apply_filters( 'access_control_allow_origin', '*' ) );
$response->header( 'Cache-Control', 'max-age=' . apply_filters( 'api_max_age', WEEK_IN_SECONDS ) );
return $response;
}
<?php
function list_books( $request ) {
$args = $request['query_args'];
$book_args = array(
'post_type' => 'books',
'post_status' => 'publish',
'posts_per_page' => 25,
'ignore_sticky_posts' => true,
);
$standard_params = array(
'order',
'orderby',
'author',
'post_type',
'ignore_sticky_posts',
'paged',
'page',
'nopaging',
'posts_per_page',
's',
);
foreach ( $standard_params as $standard_param ) {
if ( isset( $args[ $standard_param ] ) && ! empty( $args[ $standard_param ] ) ) {
$book_args[ $standard_param ] = $args[ $standard_param ];
}
}
$the_query = new WP_Query( $book_args );
$return = array(
'total' => (int) $the_query->found_posts,
'count' => (int) $the_query->post_count,
'pages' => (int) $the_query->max_num_pages,
'posts_per_page' => (int) $book_args['posts_per_page'],
'query_args' => $book_args,
'books' => array(),
);
if ( $the_query->have_posts() ):
$i = 0;
while ( $the_query->have_posts() ):
$the_query->the_post();
$post_id = get_the_ID();
$rating = get_post_meta( $post_id, '_book_rating', true );
$rating = ( empty( $rating ) ) ? false : (int) $rating;
$thumbnail = get_post_thumbnail_id( $post_id );
if ( empty( $thumbnail ) ) {
$thumbnail = false;
} else {
$thumbnail = wp_get_attachment_image_src( $thumbnail, 'thumbnail' );
if ( is_array( $thumbnail ) ) {
$thumbnail = array(
'src' => $thumbnail[0],
'width' => $thumbnail[1],
'height' => $thumbnail[2],
);
}
}
$return['books'][ $i ] = array(
'ID' => $post_id,
'title' => get_the_title( $post_id ),
'rating' => $rating,
'thumbnail' => $thumbnail,
);
$i ++;
endwhile;
wp_reset_postdata();
endif;
$response = new WP_REST_Response( $return );
$response->header( 'Access-Control-Allow-Origin', apply_filters( 'access_control_allow_origin', '*' ) );
$response->header( 'Cache-Control', 'max-age=' . apply_filters( 'api_max_age', WEEK_IN_SECONDS ) );
return $response;
}
<?php
function register_books_rest_fields() {
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'
),
)
);
}
add_action( 'rest_api_init', 'register_books_rest_fields' );
<?php
function register_books_rest_routes() {
register_rest_route( 'app/v1', '/books', array(
'methods' => 'GET',
'callback' => 'list_books',
'args' => array(
'query_args' => array(
'default' => array(),
),
),
) );
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 ) {
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;
}
),
),
) );
}
add_action( 'rest_api_init', 'register_books_rest_routes' );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment