For the past few years, I have been working more and more with Node.js and proportionally less frequently with PHP. As might be expected, though the underpinnings of web behavior is platform agnostic, the architecture for the web application layer changes to suite the technology stack in which you are building. In fact, one of the marks of a savvy engineer is the ability to leverage the best parts of a technology in the way they build their software. However, I found myself spending far too much time trying to relearn techniques in PHP for projects as I came back to them, so I decided to see if I could build a lightweight routing system in PHP that would mirror some of the patterns I use in my Node.js work every day.
Anyone who has worked with Express, Hapi, Django, Rails or even Grails can understand the ease of route declaration with something like this:
1 2 3 4 5 6 7 8 |
server.route('/profile/{username}', function (req, res) { try { var user = User::getUser(req.param.username); res.send(user.toJson()); } catch (e) { res.send(e).status(500); } }; |
In just a few lines of extremely readable code, several things are happening:
This type of pattern typically exposes enough options on the response object to allow the coder to modify headers or do other manipulations before sending the final result.
I selfishly wanted to be able to do the same type of thing in PHP, but the libraries I found were either too PHP-ish for my taste or simply were much more heavy-handed than what I cared for. Rather than giving up, I thought I would build a composer package that would do just the heavy lifting I needed but stay light enough to allow for extensive customization.
Enter guahanweb/php-router. This was my take at bringing some of the routing strengths of my JavaScript packages into some of my PHP code.
My server of choice for the past few years has been Nginx, and I decided I would try to configure the server to serve all non-static content to my index.php
file. This gave me a single entry point from which I would set up my routing. Rebuilding Nginx with the WebDav library also let me enable additional HTTP verbs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# serve static files directly location ~* ^/(css|js|img|font)/ { root /var/www/<my-project>/assets; } # serve all other requests to index.php location / { root /var/www/<project-domain>; index index.php index.html index.htm; include /usr/local/etc/nginx/conf.d/php-fpm; dav_methods PUT DELETE; if (!-e $request_filename) { rewrite ^(.+)$ /index.php last; } error_page 404 /index.php; } |
Once I had the server configured and serving requests as I wished, I started building a few classes that would let me manage my routes easily.
Three classes were required to support the pattern I was after: a Request, a Response and a Router. When a new route is registered, the handler will be passed both a Request and Response in order for the developer to manage behavior as needed. To use this library, just start by installing via Composer.
1 |
$ composer require guahanweb/php-router |
Once installed into your application, you can simply autoload and use the Router and start managing routes:
1 2 3 4 5 6 7 8 9 10 11 |
require './vendor/autoload.php'; use GuahanWeb\Http; $router = Http\Router::instance(); $router->get('/', function ($req, $res) { // This will now process all the root requests $res->send('Hello, world!'); }); $router->process(); |
Once routing was functional, I chose to set up Twig for my template rendering, and I was able to work on full separation of concerns in my application. I created a few page helpers to worry with the explicit rendering and hooked them up like this:
1 2 3 4 5 6 |
$router->get('/profile/{username}', function ($req, $res) { $page = new Page(); $res->send($page->render('profile.html', array( 'user' => User::getUser($req->username) ))); }); |
While this is a bit of oversimplification, you get the idea of how I can quickly set up numerous routes in a very short amount of time. For full documentation of current features, feel free to check out the project on Github.
Happy routing!