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).
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
16 public function authorise()17 {18 return current_user_can('manage_options');19 }20
21 public function handler(WP_REST_Request $request)22 {23 wp_send_json_success([24 'status' => 'success',25 'response' => 'pong',26 ]);27 }28}
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 | |
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 |
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%', 'json' => '%param% must be a valid JSON string', 'url' => '%param% must be a valid URL'];
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.