Simple Request Router via PHP and Apache/.htaccess
I’ve written many articles about how to redirect requests. Even so, I still get questions about how to set up a simple HTTP request router. As in you want to redirect or route all requests to some file or location. This is useful for building CMSs and scripts that handle traffic. For example, WordPress uses a simple request router when permalinks are enabled. For this tutorial, we’ll set this up using Apache/.htaccess and PHP.
This technique is an excellent starting point for making your own (simple) content management system.
Contents
How WordPress does it
To get a better idea of what we’re doing here. Let’s look at WordPress, a widely used CMS that many are familiar with. When permalinks are enabled, WordPress redirects all incoming HTTP traffic to the index.php
file. To do this, the following bit of .htaccess is added to the site’s root .htaccess file:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Notice the path specified in the RewriteRule
, which points to WordPress’ main index.php
file. Inside of that file is the following PHP code:
define('WP_USE_THEMES', true);
require( dirname( __FILE__ ) . '/wp-blog-header.php' );
From there WordPress calls wp-blog-header.php
, which includes the following bit of conditional PHP logic:
if ( !isset($wp_did_header) ) {
$wp_did_header = true;
// Load the WordPress library.
require_once( dirname(__FILE__) . '/wp-load.php' );
// Set up the WordPress query.
wp();
// Load the theme template.
require_once( ABSPATH . WPINC . '/template-loader.php' );
}
..and it’s off to the races. This code then continues to load all of the required files and scripts necessary for WordPress to output the appropriate post, page, archive, search results or whatever is needed to fulfill the request.
So to sum up WordPress request router:
- Use .htaccess code to route all traffic to
index.php
index.php
then callswp-blog-header.php
wp-blog-header.php
then continues with further logic, etc.
Of course, the PHP and other “logic” employed by WordPress is deep and wide. Feel free to continue down that rabbit hole if you dare (you will learn a LOT, trust me). For this tutorial, we’re going to keep the router logic as simple as possible. You can always modify and extend the basic example to suit your specific project needs.
Build your own simple request router
Now that we’ve seen how WordPress does it, let’s break things down and simplify the routing technique. The goal is to build the simplest PHP router possible. So all incoming traffic will redirect to index.php
, which then will route to the necessary PHP files that deliver the page views.
To give you some context, here is what the path structure will look like:
/app
/404.php
/about.php
/archive.php
/contact.php
/home.php
/index.php
The goal is to keep things super simple. In order to focus on the main point: how to route traffic via PHP and .htaccess. So nothing fancy but this is well-tested and it just works. So you can get the idea and go from there, customizing and extending things however you’d like. Here are three steps to make it happen:
Step 1: Add .htaccess
Create a new folder named app
. In it, create an .htaccess file. Add these rules:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /app/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L,QSA]
</IfModule>
This basically is just a simplified version of the WordPress permalink (routing) rules. Notice the RewriteBase
specifies our /app/
directory. Collectively these rules redirect all incoming traffic to the root index.php
file. Fine-tune as desired.
Step 2: Create index.php
Next, create a file named index.php
and place it in the root directory of your project. This will be the main routing switch that handles the conditional loading of files. Inside of index.php
, add the following code:
<?php
$request_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null;
if ($request_uri === '/app/' || $request_uri === '/app') {
$route = '/home.php';
} elseif ($request_uri === '/app/about/' || $request_uri === '/app/about') {
$route = '/about.php';
} elseif ($request_uri === '/app/archive/' || $request_uri === '/app/archive') {
$route = '/archive.php';
} elseif ($request_uri === '/app/contact/' || $request_uri === '/app/contact') {
$route = '/contact.php';
} else {
$route = '/404.php';
}
require __DIR__ . $route;
No changes need made to this code. What is it doing though. Basically this code grabs the requested path via $_SERVER['REQUEST_URI']
. It then checks the path and responds with the appropriate PHP file. For example, requests for /about
will be served about.php
, and so forth. The logic is very basic, and is very fast.
Step 3: Create the view files
Lastly, create the five view files, 404.php
, about.php
, archive.php
, contact.php
, and home.php
. Here are the contents of each of these files, respectively:
<?php // 404 Not Found
echo '<h1>404 - Not Found</h1>';
<?php // About Page
echo '<h1>About us</h1>';
<?php // Archive
echo '<h1>Welcome to the archive</h1>';
<?php // Contact
echo '<h1>Contact us!</h1>';
<?php // Homepage
echo '<h1>Welcome to the homepage</h1>';
Again, we’re keeping things super simple, so the above code is just enough to know that things are working. Obviously you can build out the page views as much as needed. Once you see how things work, you can rename pages, add pages, etc.
Testing in a browser
We now can upload the /app/
directory to the server and test that everything is working. In a browser, you can visit the following pages:
https://example.com/
https://example.com/about/
https://example.com/archive/
https://example.com/contact/
https://example.com/404
Remember to replace example.com
with your actual domain. Each page should display the corresponding view file. Any request not included in the above list will result in the 404 view displayed.
Download
Download the finished app here. No license just go have fun and build stuff :)
Usage: Unzip download file, upload /app/
to your server, and visit in a browser.