PHPackages                             aivec/wordpress-router - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. aivec/wordpress-router

ActiveLibrary[HTTP &amp; Networking](/categories/http)

aivec/wordpress-router
======================

WordPress request router. Middleware, JWT, and nonce checks included.

v7.3.1(11mo ago)52.3k[2 PRs](https://github.com/aivec/wordpress-router/pulls)GPL-2.0-onlyPHP

Since Oct 20Pushed 11mo ago1 watchersCompare

[ Source](https://github.com/aivec/wordpress-router)[ Packagist](https://packagist.org/packages/aivec/wordpress-router)[ RSS](/packages/aivec-wordpress-router/feed)WikiDiscussions master Synced 5d ago

READMEChangelogDependencies (11)Versions (42)Used By (0)

WordPress REST Router
=====================

[](#wordpress-rest-router)

This package provides a routing library for WordPress with WordPress specific wrappers such as nonce verification and user role checking. The backbone of this package uses [FastRoute](https://github.com/nikic/FastRoute), a small and succinct route resolver. `FastRoute` is also the route resolver used by the popular micro-framework [Slim](http://www.slimframework.com/).

The Problem
-----------

[](#the-problem)

Routing in WordPress is a pain for plugin authors. It relies solely on `$_POST` object keys to resolve routes if you go with WordPress' traditional way of registering AJAX handlers via `admin-ajax.php`. You could use WordPress' [REST API](https://developer.wordpress.org/rest-api/), but you don't have control of *when* routes are resolved. This is important to developers who create extensions for other plugins where the load order is out of their control. This package also differs from WordPress' implementation in that it doesn't provide `validate` and `sanitize` callbacks, opting instead for generic middlewares.

Features
--------

[](#features)

This library provides many features to streamline the provisioning of routes, as well as some optional default middlewares. The main features are as follows:

- Role based route registration (editor, administrator, etc.)
- Automatic nonce verification
- URL parameters (**NOT REGEX** 😁)
- Passthru routing (non-AJAX routes)
- Helpers for generating HTML forms
- JWT route registration
- JWT settings page for automatic key pair generation

Installation
------------

[](#installation)

Install with [composer](https://getcomposer.org/):

```
$ composer require aivec/wordpress-router
```

If you plan on using this package in a plugin, we *highly* recommend namespacing it with [mozart](https://github.com/coenjacobs/mozart). If you don't, things may break in an impossible to debug way. [You have been warned](https://wptavern.com/a-narrative-of-using-composer-in-a-wordpress-plugin).

Usage Guide
-----------

[](#usage-guide)

- [Public Route](#public-route)
    - [Calling the Public Route](#calling-the-public-route)
- [Private Route](#private-route)
    - [Calling the Private Route](#calling-the-private-route)
- [URL Parameters](#url-parameters)
- [Form Data](#form-data)
- [Making Everything Easier](#making-everything-easier)

Public Route
------------

[](#public-route)

A public route refers to a route without nonce verification. A public route is accessible by anyone, from anywhere.

```
use Aivec\WordPress\Routing\Router;
use Aivec\WordPress\Routing\WordPressRouteCollector;

// First, we declare our routes by extending the `Router` class:
class Routes extends Router {

    /**
     * This is where we define each route
     */
    public function declareRoutes(WordPressRouteCollector $r) {
        $r->addPublicRoute('GET', '/hamburger', function () {
            return 'Here is a public hamburger.';
        });
    }
}

// Next, we instantiate the `Routes` class with a unique namespace and listen for requests
$routes = new Routes('/mynamespace');
$routes->dispatcher->listen();
```

### Calling the Public Route

[](#calling-the-public-route)

You can test the route from the command line, like so:

```
$ curl -X GET http://www.my-site.com/mynamespace/hamburger
'Here is a public hamburger.'
```

Or, you can use `jQuery`'s `ajax` function to send a request from a script loaded into a WordPress page:

```
jQuery.ajax("http://www.my-site.com/mynamespace/hamburger", {
  success(data) {
    var response = JSON.parse(data);

    console.log(response); // Here is a public hamburger.
  },
});
```

Private Route
-------------

[](#private-route)

A private route refers to a route with nonce verification.

```
use Aivec\WordPress\Routing\Router;
use Aivec\WordPress\Routing\WordPressRouteCollector;

// First, extend the `Router` class:
class Routes extends Router {

    /**
     * This is where we define each route
     */
    public function declareRoutes(WordPressRouteCollector $r) {
        /**
         * `add` is the default way to register a route with nonce verification
         */
        $r->add('POST', '/hamburger', function () {
            return 'Here is a private hamburger.';
        });
    }
}
```

After declaring our routes, we instantiate the `Routes` class with a unique namespace.

This time, we pass in a nonce key and nonce name as the second and third argument, respectively.

Since nonce handling requires WordPress core functions, we must instantiate the `Routes`class after core functions have been loaded. You can use the `init` hook, or any other appropriate hook to ensure core functions are loaded.

```
$routes = null;
add_action('init', function () use ($routes) {
    $routes = new Routes('/mynamespace', 'nonce-key', 'nonce-name');
    $routes->dispatcher->listen();
});
```

### Calling the Private Route

[](#calling-the-private-route)

In general, private routes are called via AJAX from a JavaScript file on the WordPress site. To do this, we must make the nonce available to the script in which we want to call the route.

Leveraging `wp_localize_script`, we can use a helper method from the `Routes` class to inject the nonce variables:

```
add_action('wp_enqueue_scripts', function () use ($routes) {
    wp_enqueue_script(
        'my-script',
        site_url() . '/wp-content/plugins/my-plugin/my-script.js',
        [],
        '1.0.0',
        false
    );

    wp_localize_script('my-script', 'myvars', $routes->getScriptInjectionVariables());
});
```

Now, `my-script.js` will have the nonce variables we need to make the call.

```
// my-script.js
jQuery.ajax(`${myvars.endpoint}/hamburger`, {
  method: "POST",
  data: {
    [myvars.nonceKey]: myvars.nonce,
  },
  success(data) {
    var response = JSON.parse(data);

    console.log(response); // Here is a private hamburger.
  },
});
```

URL Parameters
--------------

[](#url-parameters)

Curly braces are used to define a URL parameter.

URL parameters are parsed and then inserted into an `$args` variable, which is always the *first* parameter given to the handler function.

```
$r->add('POST', '/hamburger/{burgername}', function (array $args) {
    return 'Here is a ' . $args['burgername'] . ' hamburger.';
});
```

```
// my-script.js
jQuery.ajax(`${myvars.endpoint}/hamburger/mushroom`, {
  method: "POST",
  data: {
    [myvars.nonceKey]: myvars.nonce,
  },
  success(data) {
    var response = JSON.parse(data);

    console.log(response); // Here is a mushroom hamburger.
  },
});
```

You can define as many parameters as you want.

```
$r->add('POST', '/hamburger/{burgername}/{count}', function (array $args) {
    return 'Here are ' . $args['count'] . ' ' . $args['burgername'] . ' hamburgers.';
});
```

You can also limit the type of parameter accepted, as well as provide your own patterns for more granular control.

```
// Matches /user/42, but not /user/xyz
$r->add('POST', '/user/{id:\d+}', .....);

// Matches /user/foobar, but not /user/foo/bar
$r->add('GET', '/user/{name}', .....);

// Matches /user/foo/bar as well
$r->add('GET', '/user/{name:.+}', .....);
```

There are many possibilities for route definitions. For detailed information about how routes are resolved, refer [here](https://github.com/nikic/FastRoute#defining-routes).

Form Data
---------

[](#form-data)

The router expects `POST` requests to be sent with a content type of `application/x-www-form-urlencoded`. Form data is sent as a JSON encoded string as the value of a `payload` key in the body of the request.

```
// $payload contains the decoded JSON key-value array
$r->add('POST', '/hamburger', function (array $args, array $payload) {
    $ingredients = join(' and ', $payload['ingredients']);
    return 'I want ' . $ingredients . ' on my hamburger.';
});
```

```
// my-script.js
jQuery.ajax(`${myvars.endpoint}/hamburger`, {
  method: "POST",
  data: {
    [myvars.nonceKey]: myvars.nonce,
    payload: JSON.stringify({
      ingredients: ["pickles", "onion"],
    }),
  },
  success(data) {
    var response = JSON.parse(data);

    console.log(response); // I want pickles and onion on my hamburger.
  },
});
```

Making Everything Easier
------------------------

[](#making-everything-easier)

As we've seen above, private routes require a nonce key-value pair to be present in the body of a `POST` request. You may have noticed that we excluded `GET` requests in those examples. This is because `GET` requests don't have body content, which means that the nonce variables must be set as URL query parameters. This whole process is tedious, and we can do better.

For people transpiling their JavaScript, we recommend using [axios](https://github.com/axios/axios) with our [helper library](https://github.com/aivec/reqres-utils). This completely abstracts nonce handling and JSON encoding, as well as automatically setting nonce variables in the request regardless of the request method (`GET`, `POST`, `PUT`, etc.).

The following is the [Form Data](#form-data) example, rewritten using these libraries:

```
// my-script.js
import axios from "axios";
import { createRequestBody } from "@aivec/reqres-utils";

axios
  .post(
    `${myvars.endpoint}/hamburger`,
    createRequestBody(myvars, {
      ingredients: ["pickles", "onion"],
    })
  )
  .then(({ data }) => {
    console.log(data);
  });
```

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance50

Moderate activity, may be stable

Popularity20

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity70

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~55 days

Recently: every ~261 days

Total

38

Last Release

349d ago

Major Versions

v2.2.0 → v3.0.02020-02-25

v3.1.2 → v4.0.02020-04-16

v4.1.1 → v5.0.02021-01-21

v5.1.0 → v6.0.02021-04-26

v6.0.2 → v7.0.02021-04-29

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/49274188?v=4)[Aivec LLC.](/maintainers/Aivec)[@aivec](https://github.com/aivec)

---

Top Contributors

[![EvanShaw](https://avatars.githubusercontent.com/u/6827717?v=4)](https://github.com/EvanShaw "EvanShaw (43 commits)")

### Embed Badge

![Health badge](/badges/aivec-wordpress-router/health.svg)

```
[![Health](https://phpackages.com/badges/aivec-wordpress-router/health.svg)](https://phpackages.com/packages/aivec-wordpress-router)
```

###  Alternatives

[shopify/shopify-api

Shopify API Library for PHP

4634.8M16](/packages/shopify-shopify-api)[omniphx/forrest

A Laravel library for Salesforce

2724.4M8](/packages/omniphx-forrest)[league/route

Fast routing and dispatch component including PSR-15 middleware, built on top of FastRoute.

6633.1M115](/packages/league-route)[xeroapi/xero-php-oauth2

Xero official PHP SDK for oAuth2 generated with OpenAPI spec 3

1054.3M14](/packages/xeroapi-xero-php-oauth2)[vgrem/php-spo

PHP Office 365 library. It allows to performs CRUD operations against Office 365 resources via an REST/OData based API

3741.4M5](/packages/vgrem-php-spo)[bigcommerce/api

Enables PHP applications to communicate with the Bigcommerce API.

1501.1M8](/packages/bigcommerce-api)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
