For one of the courses I teach I was in need of a PHP Router. Having explored the available routers out there I found they either were:
- Outdated
- Not object oriented
(sorry Klein (which has been updated by now, but wasn’t at the time)) - Rather bad at the separation of concerns
(sorry Ham & Klein; a router should only route, not handle templates/logging/sessions/…) - Not powerful enough
(sorry JREAM/route; there’s more than justGET
you know) - To be part of a bigger framework
(sorry Silex and Slim) - Bloated for a one-time lab/to get things quickly up and running
(sorry Symfony Routing) - …
In the end I decided to write one myself which I’ve polised for publication over the past few days. The result is bramus/router
, a lightweight and simple object oriented PHP Router. A typical implementation of the class is this:
// Require composer autoloader
require __DIR__ . '/vendor/autoload.php';
// Create a Router
$router = new \Bramus\Router\Router();
// Custom 404 Handler
$router->set404(function() {
header('HTTP/1.1 404 Not Found');
echo '404, route not found!';
});
// Static route: / (homepage)
$router->get('/', function() {
echo '<h1>bramus/router</h1><p>Try these routes:<p><ul><li>/hello/<em>name</em></li><li>/blog</li><li>/blog/<em>year</em></li><li>/blog/<em>year</em>/<em>month</em></li><li>/blog/<em>year</em>/<em>month</em>/<em>day</em></li></ul>';
});
// Dynamic route: /hello/name
$router->get('/hello/(\w+)', function($name) {
echo 'Hello ' . htmlentities($name);
});
// Dynamic route with (successive) optional subpatterns: /blog(/year(/month(/day(/slug))))
$router->get('/blog(/\d{4}(/\d{2}(/\d{2}(/[a-z0-9_-]+)?)?)?)?', function($year = null, $month = null, $day = null, $slug = null) {
if (!$year) { echo 'Blog overview'; return; }
if (!$month) { echo 'Blog year overview (' . $year . ')'; return; }
if (!$day) { echo 'Blog month overview (' . $year . '-' . $month . ')'; return; }
if (!$slug) { echo 'Blog day overview (' . $year . '-' . $month . '-' . $day . ')'; return; }
echo 'Blogpost ' . htmlentities($slug) . ' detail (' . $year . '-' . $month . '-' . $day . ')';
});
// Thunderbirds are go!
$router->run();
(Yes, you must get your PCRE mojo on in order to define dynamic routes)
bramus/router
also supports before route middlewares, before router middlewares, and after router middleware. These features allow one to integrate bramus/router
with their favorite library (logging, templating, …):
$router = new \Bramus\Router\Router();
$tpl = new \Acme\Template\Template();
$router->get('/', function() use ($tpl) {
$tpl->load('home.tpl');
$tpl->setdata(array(
'name' => 'Bramus!'
));
});
$router->run(function() use ($tpl) {
$tpl->display();
});
An extensive writeup of these features is available on GitHub.
A final note worth mentioning is that bramus/router
is installable via Composer and is unit tested.
bramus/router
(GitHub) →
bramus/router
on Packagist →
bramus/router
Travis CI build status →
Is it possible to add file-extension (like .html) to the router? Could the movie database be like this?
/movies.html (overview)
/movies,2.html (overview page 2)
/movie/123.html (movie detaisl for movie id 123)
I cannot find a solution to add .html as extension.
Thanks so far!
Hi,
I’m trying to understand how your router works, but I’m stuck here:
My blog class is located in /module/blog/Blog.css,
and I’m trying to do something like:
$router->get(‘/blog’, ‘\module\blog\Blog@Index’);
Content of blog class is just basic like:
class Blog
{
function Index() {
print ‘Blog Page’;
}
}
But for some reason I can get it to print Blog page, and no errors are thrown
Could you point me to any resource that integrates some kind of security or login for secured urls? great work, thanks