-
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
63: Practice Exercise: Building a Simple RESTful API with Routing
A few years ago, I was reviewing a PR for a junior developer who had built a small internal tool. When I looked at the file structure, I nearly gasped. He had created a separate PHP file for every single API endpoint: get_user.php, update_user.php, delete_user.php, and so on. It worked, sure, but the moment we needed to add a global authentication check or a standardized error response, he had to manually edit thirty different files. It was a maintenance nightmare waiting to happen.
That's where a proper router comes in. Instead of letting the web server decide which file to execute based on the URL, we route every single request through a single entry point—usually index.php—and then use logic to decide which piece of code should handle that specific request. This is the backbone of almost every modern PHP framework you'll encounter.
Decoding the Request URI and Method
To build a router, you first need to know two things: where the user is trying to go (the URI) and what they want to do (the HTTP Method). In PHP, we pull this from the $_SERVER superglobal. I usually start by cleaning up the REQUEST_URI to remove query strings, because if a user hits /books?sort=desc, your router shouldn't treat that as a different page than /books.
$requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$requestMethod = $_SERVER['REQUEST_METHOD'];
// A simple routing map
$routes = [
'GET' => [
'/books' => 'getAllBooks',
'/books/status' => 'getBookStatus',
],
'POST' => [
'/books' => 'createBook',
],
];
By mapping methods to function names (or controller methods), you decouple the URL from the actual file system. If you decide to change /books to /library/volumes, you change one line in your map, not a filename and every link in your frontend.
Handling Dynamic IDs in URLs
Static routes are easy, but RESTful APIs almost always need dynamic segments, like /books/123. You can't hardcode every possible ID into an array. This is where regular expressions come into play. I prefer using preg_match to identify patterns. For example, a pattern like #^/books/(\d+)$# tells PHP: "Look for a URL that starts with /books/ followed by one or more digits."
When a match is found, the digits are captured in an array. You can then pass that ID directly into your data fetching logic. This keeps your API clean and predictable, which is exactly what frontend developers expect when they're consuming your endpoints.
Standardizing the JSON Pipeline
One thing I see people forget is that a REST API isn't just about the logic; it's about the contract. If your router handles the request but your function returns a raw string or, heaven forbid, an HTML error page, you've broken that contract. Every single path in your router should ultimately lead to a standardized response.
I always recommend wrapping your output in a helper function. Set the Content-Type: application/json header first, then use json_encode(). This ensures that whether you're returning a list of a thousand books or a "404 Not Found" error, the client receives a consistent data format. It's a small detail, but it's the difference between a professional API and a hobby project.
📋 Practical Task
Exercise: Building a RESTful Book Catalog API
Your task is to create a simple routing system in a single index.php file that manages a mock library of books. You don't need a real database for this; a hardcoded array of books will do.
Requirements:
- The Data: Create an array of books, where each book has an
id,title, andauthor. - The Router: Use
$_SERVER['REQUEST_URI']and$_SERVER['REQUEST_METHOD']to handle the following endpoints:GET /books: Return the entire list of books as JSON.GET /books/{id}: Use a regular expression to capture the ID. If the book exists, return it as JSON; otherwise, return a 404 error in JSON format.POST /books: Simulate adding a book. Read thephp://inputstream to get JSON data, and return a 201 Created response with the "created" book object.
- Headers: Ensure every response is sent with the
Content-Type: application/jsonheader. - Error Handling: If a route is not defined or a method is not allowed for a specific URI, return a 405 Method Not Allowed or 404 Not Found JSON response.
There are no comments for now.