Basic Routing in PHP with AltoRouter

By: Tyler Longren

I’ve been using AltoRouter for help with building simple API’s. A full framework (even a micro-framework), like Slim, is usually overkill for my needs, and often, any kind of routing class is overkill. A .htaccess file with the proper rewrite rules will usually suffice.

When I do need a bit more control than a .htaccess file provides, I usually go with AltoRouter. AltoRouter is really easy to use.

First thing to do when using AltoRouter, or pretty much any PHP routing class/script, is to direct all requests to index.php. We do this with a .htaccess file. Here’s the .htaccess file I usually use with a project using AltoRouter:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /index.php [L]

That will direct all requests to your site to index.php. Inside index.php is where we setup AltoRouter, define our routing rules, and specify any parameters that we want to capture. A basic example of an index.php file using AltoRouter can be seen below.


<?php
header("Content-Type: text/html");
include dirname(__FILE__) . '/includes/AltoRouter.php';

$router = new AltoRouter();
$router->setBasePath('');
/* Setup the URL routing. This is production ready. */

// Main routes that non-customers see
$router->map('GET','/', 'home.php', 'home');
$router->map('GET','/home/', 'home.php', 'home-home');
$router->map('GET','/plans/', 'plans.php', 'plans');
$router->map('GET','/about/', 'about.php', 'about');
$router->map('GET','/contact/', 'contact.php', 'contact');
$router->map('GET','/tos/', 'tos.html', 'tos');

// Special (payments, ajax processing, etc)
$router->map('GET','/charge/[*:customer_id]/','charge.php','charge');
$router->map('GET','/pay/[*:status]/','payment_results.php','payment-results');

// API Routes
$router->map('GET','/api/[*:key]/[*:name]/', 'json.php', 'api');

/* Match the current request */
$match = $router->match();
if($match) {
  require $match['target'];
}
else {
  header("HTTP/1.0 404 Not Found");
  require '404.html';
}
?>

Lines 10-15 are just standard routes being setup, we could easily do this with a .htaccess file. The next block, with the “Special” comment title, is a little more involved. But only because we’re passing a parameter or two to our PHP controller.

When I say PHP controller, I’m referencing the third parameter in the AltoRouter map() method. The first parameter is the HTTP request method, usually either GET or POST. The second parameter is the route we want to watch for. The third parameter is the controller, or the PHP file that we want when the route from parameter two is matched. And the fourth parameter is just a unique name for that route.

If you’re using named parameters in your routes, like you see being done on lines 18 and 19 in the index.php gist, you’re going to want to access them within your controller. Notice the very end of the index.php gist, specifically, everything below the /* Match the current request */ comment. That’s where we’re doing the actual matching, if the current URL matches a defined route, then we require the controller.

Before that though, we’re actually setting the $match variable. Since we’re setting $match before including our controller, $match should be available for use within our controller, which is awesome!

Say we’re charging a customer, and this is done by hitting /charge/the_customer_id/, where the_customer_id is an actual customer ID. In our controller, charge.php, we can access the_customer_id named parameter as seen below. It’s available in $match[‘params’][‘customer_id’].


<?php
$customer = new Customer();

$customer_id = $match['params']['customer_id'];

if ($customer->valid_customer($customer_id) && $customer->needs_paid($customer_id)) {
  $customer->pay($customer_id);
}
?>

You can use all sorts of limits on your named parameters, like integer matching, alphanumeric matching, and even hexadecimal character matching. A useful list of named parameter limits and some examples can be seen in the AltoRouter readme. Comments are open, so please let me know if I’ve missed something or am just totally off base somewhere. Thanks!!

Note: Tyler’s blog is going down today (15 Sept 2018) I loved his article so I saved this, in case his blog never running up again.

Leave a Reply