[API] Add a custom endpoint to WordPress REST API with Pagination
https://fancysquares.blog/add-a-custom-endpoint-to-wordpress-rest-api
Add a custom endpoint to WordPress REST API with Pagination
Published: October 18th 2019
Are you trying to add a custom endpoint and/or route to the WordPress REST API?
Are you then stuck in a rut if its missing pagination?
Have no fear, I got your back! (full code is the bottom before that are small explanations explaining what’s going on)
ADDING A CUSTOM ENDPOINT TO WORDPRESS REST API
We are going to start with extending WP_REST_CONTROLLER
class REFINED_POST_ENDPOINT extends WP_REST_Controller { } add_action( 'rest_api_init', function () { $controller = new REFINED_POST_ENDPOINT(); $controller->register_routes(); } );
In REFINED_POST_ENDPOINT
is where we’ll place code specifics and the add_action
is what will run all the little magical things we do (you added code, and route, this will run it).
In our newly created class we will start with the following constructor:/*** Constructor. */public function __construct() { $this->namespace = 'rmh/v1'; $this->rest_base = 'posts'; $this->post_type = 'post';}
From top to bottom:
rest base is set: yourdomain.com/wp-json/rmh/v1 (or whatever your heart desires!)
next is the base for the endpoint itself “posts”, not to be confused with the post type. (yourdomain.com/wp-json/rmh/v1/posts)
last is the post type we are getting. In this example, we are grabbing “post”
REGISTERING YOUR NEW ROUTE!
/** * Register the component routes. */ public function register_routes() { register_rest_route( $this->namespace, '/' . $this->rest_base, array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_items' ), 'permission_callback' => array( $this, 'get_items_permissions_check' ), 'args' => $this->get_collection_params(), ) ) ); }
From top to bottom:
We are combing your namespace and base together
making the request READABLE so to be clear that means this is a get request (see here for me details)
we will then get then return the code placed in our
get_items
functionit then checks to make sure we have permission to do so through our
get_items_permissions_check
and it checks what are the possible arguments that can be used with it
get_collection_params()
RETRIEVING POSTS AND SETTING RESPONSE HEADERS FOR PAGINATION (X-WP-TOTAL, X-WP-TOTALPAGES)
/** * Retrieve posts. */ public function get_items( $request ) { $args = array( 'post_type' => $this->post_type, 'posts_per_page' => $request['per_page'], 'paged' => $request['page'], //'name' => $request['slug'], ); // use WP_Query to get the results with pagination $query = new WP_Query( $args ); // if no posts found return if( empty($query->posts) ){ return new WP_Error( 'no_posts', __('No post found'), array( 'status' => 404 ) ); } // set max number of pages and total num of posts $posts = $query->posts; $max_pages = $query->max_num_pages; $total = $query->found_posts; foreach ( $posts as $post ) { $response = $this->prepare_item_for_response( $post, $request ); $data[] = $this->prepare_response_for_collection( $response ); } // set headers and return response $response = new WP_REST_Response($data, 200); $response->header( 'X-WP-Total', $total ); $response->header( 'X-WP-TotalPages', $max_pages ); return $response; }/** * Check if a given request has access to post items. */ public function get_items_permissions_check( $request ) { return true; }/** * Get the query params for collections */ public function get_collection_params() { return array( 'page' => array( 'description' => 'Current page of the collection.', 'type' => 'integer', 'default' => 1, 'sanitize_callback' => 'absint', ), 'per_page' => array( 'description' => 'Maximum number of items to be returned in result set.', 'type' => 'integer', 'default' => 10, 'sanitize_callback' => 'absint', ), ); }/** * Prepares post data for return as an object. */public function prepare_item_for_response( $post, $request ) { $data = array( 'name' => $post->post_title, 'copy' => $post->post_content, 'featured_img' => get_the_post_thumbnail_url($post->ID, 'full'), 'external_link' => get_field('external_post_link',$post->ID), 'date' => date( "F j, Y", strtotime($post->post_date)) ); return $data;}
From top to bottom get_items
:
We are setting are variables for
WP_Query
why that instead of get_posts? Because we want to return the total number of pages and posts with it as well
We then set the variables
If nothing then let us know
Set the variables for what we will loop through, total number pages and total number of posts found
Loop through the posts that will check the data we set and return it in the response
Finish
get_items
up by returning the response and setting the response headers for paginationWe then set the permission check
For
get_collection_params
we are setting thepage
andper_page
details and defaultsFor
prepare_item_for_response
we are setting the data we literally returning per post and is called above inget_items
You, of course, would set this based on your needs.
In this example, we are getting the title/content/featured image/an ACF Field/date
Now you’ll have the following:
yourdomain.com/wp-json/rmh/v1/posts
yourdomain.com/wp-json/rmh/v1/posts?page=2
etcyourdomain.com/wp-json/rmh/v1/posts?per_page=3
etcyourdomain.com/wp-json/rmh/v1/posts?per_page=5&page=3
and so on!
Last updated