WP REST Registration

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.


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:

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.

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:

namespacestringyesThe root namespace of your route classes<empty>
directorystringyesThe root directory containing your route classes<empty>
versionintnoThe version of your REST API to register1
base_urlstringyesThe 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

2namespace MyPlugin\RestApi;
4use WP_REST_Request;
5use EvoWpRestRegistration\BaseRestController;
7defined('ABSPATH') or exit;
9class PingGet extends BaseRestController
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-json
14 protected bool $indexed = true;
16 public function authorise()
17 {
18 return current_user_can('manage_options');
19 }
21 public function handler(WP_REST_Request $request)
22 {
23 wp_send_json_success([
24 'status' => 'success',
25 'response' => 'pong',
26 ]);
27 }


You can add a rules property to your controller to automatically validate parameters.

2namespace MyPlugin\RestApi;
4use WP_REST_Request;
5use EvoWpRestRegistration\BaseRestController;
7defined('ABSPATH') or exit;
9class CheckSomevar extends BaseRestController
11 protected $path = 'check-somevar';
12 protected $methods = 'POST';
13 protected $rules = [
14 'somevar' => ['required','numeric']
15 ]
17 public function handler()
18 {
19 $validated = $this->validated();
21 // Only fields with rules that have been passed will be on your validated parameters.
23 // Failure will result in a WP_Error('validation_failed') error being returned (HTTP status 400)
25 wp_send_json_success([
26 'status' => 'success',
27 'response' => 'somevar was a number',
28 ]);
29 }

Available validation rules

Rule nameArgArg 2Arg 3Description
requiredParam is required
nullableRemaining rules are skipped if null value
sometimesRemaining rules are skipped if param not set
booleanMust be either true or false
stringMust be a string
emailMust be a valid email address
urlrequire (path,query)as Arg 1Must be a valid URL
jsonMust be a decodable JSON string
numericMust be a numeric value (int or float)
arrayMust be an array
inval1val2 etcValue must be one of passed args
existstable (no prefix)columnValue must exist on the given table/column
uniquetable (no prefix)columnexclude idValue 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 BaseRestController
3 protected $rules = [
4 'somevar' => ['required','numeric']
5 ]
7 protected $messages = [
8 'required' => 'Required!'
9 ];
11 public function handler()
12 {
13 $validated = $this->validated();
15 // do stuff
16 }

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.

Part of evoMark's contribution to Free and Open Source Software (FOSS)

To read more about evoMark and our open-source software, head to our Open-Source Software page

composer require evo-mark/evo-wp-rest-registration