Simple and Reliable PHP Routing
I’ve been developing websites for a long time, mostly small projects. Some I made for myself, some for work. My biggest project was a photo and raster graphics store — a microstock site tailored for a local audience. I’ve always asked myself how to build the site’s section routing in the most optimal way.
The simplest example where routing is implemented through a switch:
<?php
// We get the "page" parameter from the URL, for example ?page=about
$page = $_GET['page'] ?? 'home';
// Navigation
echo '<a href="?page=home">Home</a> | ';
echo '<a href="?page=about">About</a> | ';
echo '<a href="?page=contact">Contact</a><hr>';
switch ($page) {
case 'home':
echo '<h2>Home Page</h2>';
break;
case 'about':
echo '<h2>About Page</h2>';
break;
case 'contact':
echo '<h2>Contact Page</h2>';
break;
default:
http_response_code(404);
echo '<h2>404 Not Found</h2>';
break;
}
?>
Every programmer has their own “handwriting” at work — their habits in structuring code, their own more convenient techniques. For example, I can’t stand when a website’s main page is located at mywebsite.com/home. When I see a site whose homepage has “home” in the URL, I imagine a five-legged dog where the fifth leg is dominant. Routing through a switch structure offers exactly that kind of solution.
I’ve always stuck to old-school PHP procedural markup — it seems the most clear and adequate to me, unlike OOP. No matter how simple or outdated the routing may look, the main thing is that it works on the latest PHP version. And what could be more important than a script that actually works?
As they say, “genius lies in simplicity.” Let’s start with the basics: a conditional statement chain — the if...elseif...else
control structure. Now I’ll tell you about it in more detail. First, we parse the link and determine what comes after the domain name:
$q = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
After that, we need to remove the trailing slash so that the link looks like mywebsite.com/about
. That is, if there’s a slash at the end of the path — /about/
— and it’s not the homepage, then PHP performs a 301 redirect to the version without the slash:
if ($q !== '/' && substr($q, -1) === '/') {
$clean = rtrim($q, '/');
if (!empty($_SERVER['QUERY_STRING'])) {
$clean .= '?' . $_SERVER['QUERY_STRING']; // save GET parameters
}
header("Location: $clean", true, 301);
exit;
}
Next, $q = trim($q, '/');
removes the slashes at the beginning and end.
Page logic. The strict comparison operator ===
is used. Using ===
in scripts increases security and predictability of behavior. It’s not exactly protection, but this operator sometimes helps to avoid certain logical errors that can lead to vulnerabilities.
if ($q === '') {
echo 'Home';
}
elseif ($q === 'about') {
echo 'About';
}
elseif ($q === 'contact') {
echo 'Contact';
}
else {
http_response_code(404);
echo '404 Not Found';
}
If the path is empty (/), the homepage is displayed. If the path is /about, the About page is displayed. On the Contact page, I also included a test for using GET parameters:
echo '<a href="/contact/?city=London">Test GET request</a>';
if (isset($_GET['city'])) {
echo 'GET Request Value: ' . $_GET['city'];
}
At the very end — the closing link of the conditional statement chain. If $q
doesn’t match any of the pages, the script returns the HTTP code 404 and displays the message “404 Not Found.”
else {
http_response_code(404);
echo '404 Not Found';
}
And the full code looks like this:
<?php
$q = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); // This is a global PHP variable
// that contains the entire request
// path — everything that comes
// after the domain name
if ($q !== '/' && substr($q, -1) === '/') { // Removes extra slash at the end
// if there is one (not the root of the site)
$clean = rtrim($q, '/');
if (!empty($_SERVER['QUERY_STRING'])) {
$clean .= '?' . $_SERVER['QUERY_STRING']; // save GET parameters
}
header("Location: $clean", true, 301);
exit;
}
$q = trim($q, '/');
echo '<a href="/">Home</a> ';
echo '<a href="about">About</a> ';
echo '<a href="contact">Contact</a> ';
echo '<br /><br />';
if ($q === '') {
echo 'Home';
}
elseif ($q === 'about') {
echo 'About';
}
elseif ($q === 'contact') {
echo 'Contact';
echo '<hr />';
echo '<a href="/contact/?city=London">Test GET request</a>';
echo '<br /><br />';
if (isset($_GET['city'])) {
echo 'GET Request Value: ' . $_GET['city'];
}
}
else {
http_response_code(404);
echo '404 Not Found';
}
?>
Thanks for your attention!
- Image: AI generated.