-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Object-Oriented PHP
-
Section 5: Working with Data
-
Section 6: Modern PHP (PHP 8)
-
Section 7: Working with Files and Networking
-
Section 8: Common PHP Frameworks Overview
-
Section 9: Tooling and Ecosystem
-
Section 10: Practical Projects
-
Section 11: Interview Practice
-
Section 12: More Standard Library
-
Section 13: Data Structures and Algorithms in PHP
-
Section 14: More Practice Exercises
-
Section 15: More Security and Best Practices
-
Section 16: More Testing and Tooling
-
Section 17: WordPress-Style CMS Concepts
-
Section 18: Advanced OOP Practice
-
Section 19: More Web Fundamentals
-
Section 20: Database Practice
-
Section 21: PHP Manual: Array Functions
-
Section 22: PHP Manual: Date and Calendar Functions
-
Section 23: PHP Manual: Filesystem and Directory Functions
-
Section 24: PHP Manual: Filter and Var Handling
-
Section 25: PHP Manual: Math Functions
-
Section 26: PHP Manual: JSON and XML
-
Section 27: PHP Manual: Network and Stream Functions
-
Section 28: PHP Manual: Error and Exception Handling
-
Section 29: PHP Manual: Output Control and Misc
-
Section 30: PHP Manual: FTP, Zip, and Mail
-
Section 31: Modern PHP Frameworks Deep Dive
-
Section 32: PHP Design Patterns
-
Section 33: More Practice Exercises
-
Section 34: PHP Performance and Deployment
-
Section 35: More Interview Practice
-
Section 36: More PHP Standard Library
-
Section 37: PHP Concurrency and Async
-
Section 38: More Web Development Practice
-
Section 39: PHP Testing Deep Dive
-
Section 40: Composer and Package Development
-
Section 41: PHP Security Deep Dive
-
Section 42: More Practical Projects
-
Section 43: Legacy PHP Maintenance
-
Section 44: More Algorithm Practice
-
Section 45: Final Practice and Review
-
Section 46: PHP for E-Commerce Patterns
-
Section 47: PHP API Design Deep Dive
-
Section 48: PHP Caching Strategies
-
Section 49: PHP Queue and Background Jobs
-
Section 50: PHP Multi-Tenancy Patterns
-
Section 51: PHP Real-Time Features
-
Section 52: PHP CMS and Content Modeling
-
Section 53: PHP Internationalization
-
Section 54: More Framework-Specific Practice
-
Section 55: PHP Legacy Code Refactoring
-
Section 56: More Practice Projects Round 2
-
Section 57: PHP Command-Line Applications
-
Section 58: PHP and Microservices
-
Section 59: More Interview and Review Round 2
149: Whiteboard Practice: Implementing a Simple Router in PHP
When you're in a technical interview and someone asks you to "implement a simple router," they aren't looking for you to rewrite the Symfony Routing component. They want to see if you understand how a request actually hits a server and how you can map a string (the URL) to a piece of executable code. It's basically a big dictionary lookup.
Let's build a minimal router for a personal portfolio site. We want to handle a few basic pages: a home page, an "About Me" page, and a "Projects" list. I'm going to keep this rawβno external libraries, just a single file.
Mapping URLs to Functions
The first thing I always do is define my "route map." In PHP, an associative array is the perfect tool for this. I'll map the URI path to a closure (an anonymous function) that handles the logic for that page. It keeps the mapping clean and separated from the execution logic.
<?php
$routes = [
'/' => function() {
echo "Welcome to my portfolio!";
},
'/about' => function() {
echo "I'm a software engineer who loves PHP.";
},
'/projects' => function() {
echo "Check out my latest GitHub repos.";
},
];
?>
Dispatching the Request
Now I need to figure out where the user is actually trying to go. I'll grab the request URI from the $_SERVER superglobal. The goal here is to take that URI, look it up in my $routes array, and if it exists, execute the function associated with it.
$requestUri = $_SERVER['REQUEST_URI'];
if (array_key_exists($requestUri, $routes)) {
$routes[$requestUri]();
} else {
http_response_code(404);
echo "404 - Page Not Found";
}
?>
The Request URI Trap
I just tested this locally, and it works... until I tried adding a query parameter to the URL, like /about?referrer=twitter. Suddenly, I'm getting a 404. Why? Because $_SERVER['REQUEST_URI'] returns the entire string, including the query string. My array key is '/about', but the request is '/about?referrer=twitter'. They don't match.
This is a classic mistake. I need to strip away the query string before doing the lookup. I'll use parse_url() to isolate just the path component. Here is the corrected logic:
// Instead of using the raw URI...
$requestUri = $_SERVER['REQUEST_URI'];
// I'll parse the URL and only grab the 'path' part
$path = parse_url($requestUri, PHP_URL_PATH);
if (array_key_exists($path, $routes)) {
$routes[$path]();
} else {
http_response_code(404);
echo "404 - Page Not Found";
}
?>
Handling Trailing Slashes
One last bit of polish. In the real world, users (and some bots) are inconsistent. Some will type /about and some will type /about/. To a computer, those are different strings. To a human, they're the same page.
I'll add a quick rtrim() to the path. This ensures that if a user adds a trailing slash, we strip it off before checking the map, making the router much more resilient.
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$path = rtrim($path, '/');
// Edge case: rtrim('/') turns the home page into an empty string
if ($path === '') {
$path = '/';
}
if (array_key_exists($path, $routes)) {
$routes[$path]();
} else {
http_response_code(404);
echo "404 - Page Not Found";
}
?>π Practical Task
Build a Customer Support Portal Router
Your task is to implement a simple router for a customer support portal. Create a PHP script that maps the following paths to specific output messages using the logic we covered in the lesson:
/ticketsβ "Viewing your open support tickets."/faqβ "Frequently Asked Questions."/contactβ "Contact our support team via email."- Any other path β Return a 404 HTTP response code and the message "Portal Page Not Found."
Requirement: Ensure your router correctly handles query strings (e.g., /tickets?filter=open should still display the tickets message) and trailing slashes (e.g., /faq/ should still display the FAQ message).
There are no comments for now.