Lab 15: Capstone — REST API

Objective

Build a complete PHP REST API from scratch: HTTP routing, JSON request/response handling, SQLite persistence, input validation, error handling, and a clean layered architecture — all in pure PHP, no frameworks.

Background

This capstone ties together everything from Labs 01–14: OOP (Lab 7), PDO/SQLite (Lab 11), JSON (Lab 12), namespaces (Lab 13), and the type system (Lab 14). Real-world PHP APIs use frameworks like Laravel or Slim, but understanding the fundamentals makes you a better framework user. You'll build a product catalog REST API with full CRUD.

Time

60 minutes

Prerequisites

  • Labs 07, 08, 09, 11, 12, 13, 14

Tools

  • PHP 8.3 CLI

  • Docker image: zchencow/innozverse-php:latest

  • Database: /tmp/capstone.db (SQLite)


Lab Instructions

Step 1: Project Architecture

💡 Layered architecture separates concerns: Controllers don't touch SQL; Repositories don't know about HTTP. This means you can swap SQLite for PostgreSQL by changing only the Repository. You can test the Service layer without a database. You can add GraphQL by writing a new Controller layer.

📸 Verified Output:


Step 2: Models & DTOs

💡 Separating Product (read model) from ProductInput (write model) is the CQRS principle — Command Query Responsibility Segregation. Input DTOs carry only the fields a user can set; output models carry computed fields like id and created_at. This prevents accidental mass assignment vulnerabilities.

📸 Verified Output:


Step 3: Repository Layer

📸 Verified Output:


Step 4: Service Layer (Validation + Business Logic)

📸 Verified Output:


Step 5: HTTP Layer (Router + Controller)

📸 Verified Output:


Step 6: Bootstrap & Wire Everything

📸 Verified Output:


Step 7: Test All Endpoints

📸 Verified Output:


Step 8: Complete — Search, Stats & Summary

💡 What you've built is the core of a real PHP API. Laravel and Slim add: middleware (auth, rate limiting, CORS), dependency injection container, ORM (Eloquent/Doctrine), request/response objects (PSR-7), and better router (FastRoute). But the pattern — Route → Controller → Service → Repository — is identical. You now understand what frameworks abstract.

📸 Verified Output:


Verification

Summary

You've built a complete REST API in pure PHP 8.3:

  • Models — readonly DTOs with toArray() serialization

  • Repository — PDO/SQLite CRUD with hydrate() mapping

  • Service — validation, business rules, custom exceptions

  • Router — regex-based routing with named parameters

  • Controller — request dispatch, JSON responses

  • Test suite — all HTTP methods tested: GET, POST, PUT, DELETE

This architecture — Route → Controller → Service → Repository — is the foundation of Laravel, Symfony, and every professional PHP application.

Further Reading

Last updated