“Unlocking Hidden Potential: How WordPress Can Transform Your Data Entry into a Powerful Central API!”
Hint: even if you decide that GET
(read) requests should/can be publicly available, we still recommend that any POST
// PUT
// DELETE
(create, update, delete) requests always be guarded by a current_user_can
check.
Here is a REST controller that we added to Code Snippets in order to be able to list the employees on the site and fetch them by ID:
add_action(
'rest_api_init',
function() {
if ( ! class_exists( 'WP_REST_Controller' ) ) {
return;
}
class Employees_Controller extends WP_REST_Controller {
protected $namespace = 'custom/v1';
protected $rest_base = 'employees';
public function register_routes(): void {
register_rest_route(
$this->namespace,
"/$this->rest_base",
array(
array(
'methods' => WP_REST_Server::READABLE,
'permission_callback' => array( $this, 'get_items_permissions_check' ),
'callback' => array( $this, 'get_items' ),
'args' => $this->get_collection_params(),
),
'schema' => array( $this, 'get_public_item_schema' ),
)
);
register_rest_route(
$this->namespace,
"/$this->rest_base/(?P<employee_id>[d]+)",
array(
'args' => array(
'employee_id' => array(
'description' => __( 'Unique identifier for the employee.', 'psapi-features' ),
'type' => 'integer',
),
),
array(
'methods' => WP_REST_Server::READABLE,
'permission_callback' => array( $this, 'get_item_permissions_check' ),
'callback' => array( $this, 'get_item' ),
),
'schema' => array( $this, 'get_public_item_schema' ),
)
);
}
public function get_items_permissions_check( $request ): WP_Error|bool {
return true; // This information is public. You probably want to do a `current_user_can` check.
}
public function get_item_permissions_check( $request ): WP_Error|bool {
return $this->get_items_permissions_check( $request ); // Same as for listing all. Can be different.
}
public function get_items( $request ): WP_Error|WP_REST_Response {
$response = array();
$employees = new WP_Query( $this->prepare_posts_query_args( $request ) );
foreach ( $employees->posts as $employee ) {
$data = $this->prepare_item_for_response( $employee, $request );
$response[] = $this->prepare_response_for_collection( $data );
}
$response = rest_ensure_response( $response );
$response->header( 'X-WP-Total', $employees->found_posts );
$response->header( 'X-WP-TotalPages', $employees->max_num_pages );
foreach ( $this->prepare_link_headers( $request, $employees->max_num_pages ) as $key => $value ) {
$response->link_header( $key, $value );
}
return $response;
}
public function get_item( $request ): WP_Error|WP_REST_Response {
$employee = get_post( $request['employee_id'] );
if ( ! $employee ) {
return new WP_Error( 'rest_not_found', __( 'No employee found for the given identifier.', 'wpcom-demo' ), array( 'status' => 404 ) );
}
$response = $this->prepare_item_for_response( $employee, $request );
return rest_ensure_response( $response );
}
public function prepare_item_for_response( $item, $request ): WP_Error|WP_REST_Response {
$fields = $this->get_fields_for_response( $request );
$data = array();
if ( rest_is_field_included( 'id', $fields ) ) {
$data['id'] = $item->ID;
}
if ( rest_is_field_included( 'name', $fields ) ) {
$data['name'] = $item->post_title;
}
if ( rest_is_field_included( 'picture', $fields ) ) {
$picture = get_the_post_thumbnail_url( $item, 'full' );
$data['picture'] = empty( $picture ) ? null : $picture;
}
$data = rest_sanitize_value_from_schema( $data, $this->get_item_schema() );
$response = rest_ensure_response( $data );
if ( rest_is_field_included( '_links', $fields ) ) {
$response->add_links( $this->prepare_links( $item, $request ) );
}
return $response;
}
public function get_item_schema(): array {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$this->schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'employee',
'type' => 'object',
'properties' => array(
'id' => array(
'description' => __( 'Unique identifier for the employee.', 'wpcom-demo' ),
'type' => 'integer',
'readonly' => true,
),
'name' => array(
'description' => __( 'The name of the employee.', 'wpcom-demo' ),
'type' => 'string',
'required' => true,
),
'picture' => array(
'description' => __( 'URL to the employee profile picture.', 'wpcom-demo' ),
'type' => array( 'string', 'null' ),
'format' => 'uri',
'required' => true,
),
)
);
return $this->add_additional_fields_schema( $this->schema );
}
protected function prepare_posts_query_args( WP_REST_Request $request ): array {
return array(
'post_type' => 'employee',
'post_status' => 'publish',
'order' => $request['order'],
'orderby' => $request['orderby'],
'posts_per_page' => $request['per_page'],
'paged' => $request['page'],
's' => $request['search'] ?? '',
'tax_query' => $this->prepare_posts_taxonomy_query_args( $request ), // phpcs:ignore WordPress.DB.SlowDBQuery
);
}
protected function prepare_posts_taxonomy_query_args( WP_REST_Request $request ): array {
$tax_query = array();
if ( $request['team'] ?? false ) {
$tax_query[] = array(
'taxonomy' => 'team',
'field' => 'slug',
'terms' => array( $request['team'] ),
);
}
return $tax_query;
}
protected function prepare_link_headers( WP_REST_Request $request, int $max_pages ): array {
$link_headers = array();
$base = add_query_arg(
urlencode_deep( $request->get_query_params() ),
rest_url( $request->get_route() )
);
$next_page = $request['page'] < $max_pages ? ( $request['page'] + 1 ) : null;
if ( $next_page ) {
$link_headers['next'] = add_query_arg( 'page', $next_page, $base );
}
$prev_page = $request['page'] > 1 ? ( $request['page'] - 1 ) : null;
if ( $prev_page ) {
$link_headers['prev'] = add_query_arg( 'page', $prev_page, $base );
}
return $link_headers;
}
protected function prepare_links( WP_Post $employee, WP_REST_Request $request ): array {
$links = array();
if ( ! isset( $request['employee_id'] ) ) {
$links['self'] = array(
array(
'href' => rest_url( "$this->namespace/$this->rest_base/{$employee->ID}" ),
),
);
} else {
$links['collection'] = array(
array(
'href' => rest_url( "$this->namespace/$this->rest_base" ),
),
);
}
return $links;
}
}
( new Employees_Controller() )->register_routes();
}
);
Testing your REST routes
Post Comment