The WordPress REST API is the new way for plugins, themes and the frontend in WordPress to contact the backend to retrieve or update information. It’s already a lot easier than dealing with the labyrinthine code required to use admin-ajax
, but there’s still a fair amount of boilerplate code involved.
Here at evoMark, we’re firm believers in DRY (Don’t Repeat Yourself) coding, so we created a system to (1) utilise an object-orientation approach to declaring our routes, and (2) automatically scour allocated directories to register those routes. Ideally we wanted to just create a new route class, drop it in a directory and it would instantly be available to our theme and plugins.
So that’s what we did.
Installation
At the moment, WP REST Registration is only available via the standard Packagist repository, so you’ll need to create a composer.json
file at the root of your plugin/theme. From there, run:
composer require evo-mark/evo-wp-rest-registration
This would also be a good place to set up your PSR-4 autoloading for your REST route controllers. Go into the composer.json
file and add this at this level:
{ "autoload": { "psr-4": { "MyPluginNamespace\\": "src/" } }}
Now, composer’s autoloader will automatically scan a src
file in your plugin/theme and associate the root level namespace “MyPluginNamespace” with it.
The final installation step is to open your plugin’s entry file or your theme’s functions.php
file and require the autoload file:
<?php
require_once "vendor/autoload.php";
This will register any dependencies (like this package) and also all of your classes inside your src
folder (if you named them correctly).
Migrating to version 4
The BaseRestController
class now enforces a function signature via an abstract class method. Ensure your extended classes match the following (note the inclusion of WP_REST_Request $request
in the handler signature):
1<?php2
3use WP_REST_Request;4use EvoWpRestRegistration\BaseRestController;5
6defined('ABSPATH') or exit;7
8class RebuildClasses extends BaseRestController9{10 protected $path = 'my-section/my-endpoint';11 protected $methods = 'POST';12
13 public function authorise()14 {15 return current_user_can('manage_options');16 }17
18 public function handler(WP_REST_Request $request)19 {20 // Do things21 }22}
Registering your routes
You can register an entire directory of routes with just one command.
<?php
use EvoWpRestRegistration\RestApi;
new RestApi([ 'namespace' => 'MyPlugin\\RestApi\\', 'version' => 1, 'directory' => __DIR__ . '/src/RestApi', 'base_url' => 'my-plugin']);
The above example will load route files from the directory given with the base URL of https://yourdomain.com/wp-json/my-plugin/v1/
RestApi props
The RestApi constructor above accepts a single associative array as an argument with four possible properties inside:
Property | Type | Required | Description | Default |
namespace | string | yes | The root namespace of your route classes | <empty> |
directory | string | yes | The root directory containing your route classes | <empty> |
version | int | no | The version of your REST API to register | 1 |
base_url | string | yes | The base URL used for your routes | <empty> |
Anatomy of a route class
Inside your chosen directory, you can now start to define your route classes
1<?php2namespace MyPlugin\RestApi;3
4use WP_REST_Request;5use EvoWpRestRegistration\BaseRestController;6
7defined('ABSPATH') or exit;8
9class PingGet extends BaseRestController10{11 protected $path = 'ping';12 protected $methods = 'GET';13 // From ^3.0.0 endpoints must opt-in to be shown in the REST index at /wp-json14 protected bool $indexed = true;15 // From ^4.0.0 - the user ability required to see detailed error messages16 protected string $errorPermission = 'manage_options';17
18 public function authorise()19 {20 return current_user_can('manage_options');21 }22
23 public function handler(WP_REST_Request $request)24 {25 wp_send_json_success([26 'status' => 'success',27 'response' => 'pong',28 ]);29 }30}
Validation
You can add a rules
property to your controller to automatically validate parameters.
1<?php2namespace MyPlugin\RestApi;3
4use WP_REST_Request;5use EvoWpRestRegistration\BaseRestController;6
7defined('ABSPATH') or exit;8
9class CheckSomevar extends BaseRestController10{11 protected $path = 'check-somevar';12 protected $methods = 'POST';13 protected $rules = [14 'somevar' => ['required','numeric']15 ]16
17 public function handler()18 {19 $validated = $this->validated();20
21 // Only fields with rules that have been passed will be on your validated parameters.22
23 // Failure will result in a WP_Error('validation_failed') error being returned (HTTP status 400)24
25 wp_send_json_success([26 'status' => 'success',27 'response' => 'somevar was a number',28 ]);29 }30}
Available validation rules
Rule name | Arg | Arg 2 | Arg 3 | Description |
---|---|---|---|---|
required | Param is required | |||
nullable | Remaining rules are skipped if null value | |||
sometimes | Remaining rules are skipped if param not set | |||
boolean | Must be either true or false | |||
string | Must be a string | |||
Must be a valid email address | ||||
url | require (path,query) | as Arg 1 | Must be a valid URL | |
json | Must be a decodable JSON string | |||
numeric | Must be a numeric value (int or float) | |||
array | Must be an array | |||
in | val1 | val2 etc | Value must be one of passed args | |
not_in | val1 | val2 etc | Value must not be one of the passed args | |
exists | table (no prefix) | column | Value must exist on the given table/column | |
unique | table (no prefix) | column | exclude id | Value must not exist on the given table/column |
min | minimum | Minimum value for field, or size in KB for files | ||
max | maximum | Maximum value for field, or size in KB for files | ||
lowercase | Must not contain any uppercase characters | |||
uppercase | Must not contain any lowercase characters | |||
starts_with | val1 | val2 etc | Must start with one of the provided args | |
ends_with | val1 | val2 etc | Must end with one of the provided args | |
alpha_underscore | Can only contain alphabetical characters or underscores | |||
alpha_dash | Can only contain alphabetical characters or hyphens | |||
alpha_num | Can only contain alpha-numeric characters | |||
hex_colour | Value must be a valid hexadecimal colour value | |||
file | Value must be a file object | |||
extensions | val1 | val2 etc | File must have an extension matching one of the passed args | |
mimetypes | val1 | val2 etc | File must have mime-type matching one of the passed args | |
date | Value must be a valid date, parseable by strtotime |
Custom validation messages
By default, WP REST Registration will use the following validation error messages:
[ 'required' => '%param% is required', 'string' => '%param% must be a string', 'numeric' => '%param% must be numeric', 'array' => '%param% must be an array', 'boolean' => '%param% must be true or false', 'email' => 'Valid email address is required', 'unique' => '%value% already exists as a %param%', 'exists' => '%param% must exist on %args%', 'in' => '%param% must be one of %args%', 'not_in' => '%param% must be not be any of %args%', 'json' => '%param% must be a valid JSON string', 'url' => '%param% must be a valid URL', 'min' => '%param% must be at least %args%', 'max' => '%param% must be no more than %args%', 'lowercase' => '%param% must be lowercase', 'uppercase' => '%param% must be uppercase', 'starts_with' => '%param% must start with one of the following: %args%', 'ends_with' => '%param% must end with one of the following: %args%', 'alpha_underscore' => '%param% can only contain letters and underscores', 'alpha_dash' => '%param% can only contain letters and hyphens', 'alpha_num' => '%param% can only contain letters and numbers', 'hex_colour' => '%param% must be a hex colour', 'file' => '%param% must be a valid file', 'extensions' => '%param% must be a file with extension of %args%', 'mimetypes' => '%param% must be a file with a mime type of %args%', 'date' => '%param% must be a valid date'];
If you want to override one or more, you can simply includes a messages
property on your route class. These will be merged in with the defaults, e.g.
1class CheckSomevar extends BaseRestController2{3 protected $rules = [4 'somevar' => ['required','numeric']5 ]6
7 protected $messages = [8 'required' => 'Required!'9 ];10
11 public function handler()12 {13 $validated = $this->validated();14
15 // do stuff16 }17}
At present, your message can contain %param%
, %value%
or %args%
, which will be replaced by their respective values.
Feedback & issues
If you come accross any issues in WP REST Registration, or have any suggestions as to how we can make it better, please use the discussion or issues tab on the Github repository respectively.
We’d also appreciate any stars you have spare on the repo.