WordPress: Creating new routes (custom URLs) with WP Router

August 6, 2012

Quite often I come across projects where I need to create custom URLs and endpoints for specific functionality. I am currently working on a rather large API and working with the built in WordPress Rewrite API can be a major pain in the rear. Enter WP Router by Jonathan Brinely. WP Router takes all the fuss out of creating new endpoints by giving developers a simple and easy to understand array of values to set. I am going to show you a quick example of creating a new endpoint that will simply output some text.

Step One: Go get the plugin

WP Router is a library that has been built into a plugin. Visit the Plugins -> Add New menu on your WordPress install and you should be able to find it with the search ‘wp router’. Click the Install Now button and you will be off to the races!

Alternatively you may also download the zip file from the WordPress Repository and manually install WP Router:

http://wordpress.org/extend/plugins/wp-router/

Or you can use Git to pull the project files from Github:

https://github.com/jbrinley/WP-Router

MAKE SURE YOU ENABLE THE WP ROUTER PLUGIN!

Step Two: Get hooked

I am going to assume you understand how to add functionality through your theme functions.php file or a plugin and skip the low level detail. If you are not sure how to write a plugin read this Writing a Plugin entry on the Codex.

WP Router provides custom action hooks that you can tap into. The hook that we will be looking at is wp_router_generate_routes. This hook will pass one parameter to your function that is the WP Router object itself. This object is what you will use to add new routes. The following line is the action hook used in this demo:

add_action( 'wp_router_generate_routes', 'bl_add_routes', 20 );

Step Three: Add the route

The WP Router object that is passed to our bl_add_routes() function has a method called add_route(). The add_route() method takes two parameters:

  1. String – Unique route id
  2. Associative Array – Route arguments

For this demo you will not need all of the possible arguments. A full list of the arguments can be found in the readme.txt file.

Arguments

The arguments are in the form of an associative array. It does not matter which order you input the arguments in. Here are the arguments you will want to be familiar with:

  • `path` (required) – A regular expression to match against the request path. This corresponds to the array key you would use when creating rewrite rules for WordPress.
  • `query_vars` – An associative array, with the keys being query vars, and the values being explicit strings or integers corresponding to matches in the path regexp. Any query variables included here will be automatically registered.
  • `page_callback` (required) – A callback to use for dynamically generating the contents of the page. The callback should return the contents of
    the page. If `FALSE` is returned, nothing will be output, and control of the page contents will be handed back to WordPress. The callback will be called during the `parse_request` phase of WordPress’s page load. If `access_callback` returns `FALSE`, `page_callback` will not be called.
  • `access_callback` – A callback to determine if the user has permission to access this page. If `access_arguments` is provided, default is `current_user_can`, otherwise default is `TRUE`. If the callback returns `FALSE`, anonymous users are redirected to the login page, authenticated users get a 403 error.
    `access_callback` can be either a single callback function or an array specifying callback functions for specific HTTP methods (e.g., `GET`, `POST`, `PUT`, `DELETE`, etc.). If the latter, the `default` key will be used if no other keys match the current request method.
  • `title` - The title of the page.
  • `template` – An array of templates that can be used to display the page. If a path is absolute, it will be used as-is; relative paths allow for overrides by the theme. The string `$id` will be replaced with the ID of the route. If no template is found, fallback templates are (in this order): `route-$id.php`, `route.php`, `page-$id.php`, `page.php`, `index.php`. If FALSE is given instead of an array, the page contents will be printed before calling `exit()` (you can also accomplish this by printing your output and exiting directly from your callback function).

Here is the demo code you will use for this post:

$route_args = array(
     'path' => '^new-demo-route',
     'query_vars' => array( ),
     'page_callback' => 'bl_new_demo_route_callback',
     'page_arguments' => array( ),
     'access_callback' => true,
     'title' => __( 'Demo Route' ),
     'template' => array(
         'page.php',
         dirname( __FILE__ ) . '/page.php'
     )
);

I want to make you aware here that there are several argument that help make the title dynamic. Read the WP Router readme.txt for the full argument list

add_route

Whew! Now that that mess is over you can easily add the new route. Simply pass in the unique route id along with the argument list list so:

$router->add_route( 'demo-route-id', $route_args );

See how simple that was? If you have ever worked with the WordPress Rewrite API you will be sighing in relief. If you have not, count your blessings.

Step Four: Handle the new route

Remember back in step three when you created the page_callback argument? That is the name of the function WP Router will call when the URL containing your new route is entered. To make it easy on yourself in the beginning you have created a route that does not require any arguments passed into the callback function, and to see it working quickly you are going to output a simple string instead of doing fancy complex work right off the bat. Let’s take a look at what this callback function looks like.

function bl_new_demo_route_callback( ) {
     return "Congrats! Your demo callback is fully functional. Now make it do something fancy";
}

Simple, quick, beautiful

Step Five: View your handiwork

Now that you have gone through all that hard work it is time to view your handiwork and see what the new route looks like. At this point you should have the WP Router plugin installed and the above demo code in a functions.php file or plugin (You enabled the theme and plugins correct?). It is time to view the result. Go to http://yourdomain.com/new-demo-route (Obviously replace yourdomain.com with your real domain). I created this demo with the Twenty Twelve theme enabled so your output may look different than mine. Not to worry, if it displays in your theme then you did it right.

All together now!

Here is the demo code in its entirety, for your pleasure:

add_action( 'wp_router_generate_routes', 'bl_add_routes', 20 );

function bl_add_routes( $router ) { 
    $route_args = array(
                        'path' => '^new-demo-route',
                        'query_vars' => array( ),
                        'page_callback' => 'bl_new_demo_route_callback',
                        'page_arguments' => array( ),
                        'access_callback' => true,
                        'title' => __( 'Demo Route' ),
                        'template' => array(
                                    'page.php',
                                dirname( __FILE__ ) . '/page.php'
                        )
                );

    $router->add_route( 'demo-route-id', $route_args );
}

function bl_new_demo_route_callback( ) {
    return "Congrats! Your demo callback is fully functional. Now make it do something fancy";
}

Questions? Feel free to leave a comment below and I will get back to you ASAP