posted ago on twitter

Post image for REST Service Routing with PHP and Apache
Post image for REST Service Routing with PHP and Apache

REST Service Routing with PHP and Apache

This is just a quickie.  I had spent some time creating a routing system in PHP for services.  The goal was to bypass .htaccess or a vhost configuration file.  Basically, I wanted to map endpoints (HTTP methods + paths) to PHP methods. My goal at the time was something similar to Sinatra and/or MVC2 routes.

First, for those unfamiliar, Sinatra and “Sinatra Style” routes typically follow the pattern of:

{Http Method (get/post/put/delete)} {function}

To borrow directly from the Sinatra docs:

You can see in the above that we have defined a route pattern, in this case /hello/:name. One will run if the request method is GET and on the other if the request method is POST. the :name value is a parameter that will be captured. The RewriteRule for the same route matching would look something like this (ignoring the request method for now)

RewriteRule /hello/(.+)

So that’s Sinatra, you will see that style of routing used in a few places outside of the actual Ruby implementation. Two that come to mind are Sammy.js and Connect (node.js)

MVC2 Routes are similar. Located in the Global.asax of your MVC2 project

We don’t necessarily need the // constraints portion. If omitted, your route will still match, you just get no say in what {name} can be.

As you can see in both Sinatra and MVC2 it’s pretty handy to be able to define a route and the corresponding method/function that should be run should we get a match. Now enter PHP + Apache/mod_rewrite.

Getting bitten by some NIH syndrome, I decided to write my own route system in PHP. Yes, I know there are Sinatra Clones in PHP, what part of “Not Invented Here Syndrome” did you misunderstand =).

Well after some tinkering, I got what I wanted. The end result looked like this:

It even handled the X-HTTP-Method-Override header. The only problem was it didn’t sit well with me. I felt like I was re-inventing the wheel, especially since PHP already has tight integration with Apache.  So I decided to scrap all that work and find a better way.  To be sure, this is not nearly as pretty, but why not just let Apache handle all of the routing, it has mod_rewrite after all and its purpose built! So that’s what I did, with a touch of PHP sprinkled on top. Here is a sample .htaccess file

Keep in mind this is just a sample, but you should also notice a pattern:

?action=something&arguments[]=foo&arguments[]= bar

Here is where PHP comes in. accounts-open.php looks something like this:

MyServiceBase looks something like this:

Pay special attention to routeRequest() above, that’s were we make things happen.

Remember the pattern in the .htaccess file above:
?action=something&arguments[]=foo&arguments[]= bar

$_GET['action'] represents the method we want to call

The $_GET['arguments'] array represents the arguments, if any, we will be passing to our action.

So requestRoute() gets our necessary parameters, tests to be sure a method exists that we can call and then it dynamically invokes it for us passing our arguments, if any, along. Keep in mind that $_GET and $_POST are superglobals in PHP, so we still have access to them in whatever method we invoke.

There we have it. No reinventing the wheel and LOT less code on the PHP end and it still handles X-HTTP-Method-Override.