Skip to Content
Course content

63: Practice Exercise: Building a Simple RESTful API with Routing

Click on the "Edit" button in the top corner of the screen to edit your slide content.

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, and author.
  • 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 the php://input stream 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/json header.
  • 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.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.