What you'll learn
Every PHP web application is a machine that turns an HTTP request into an HTTP response. Once that model is clear, frameworks stop feeling magical.
- Identify the four parts of an HTTP request and response
- Read method, path, and headers through PHP
- Send correct status codes, content types, and bodies
- Explain document roots and PHP's role behind a web server
- Route several URLs through one front controller
The HTTP model
HTTP is a stateless request/response protocol. A client sends one request; a server returns one response. The browser may make many additional requests for CSS, JavaScript, fonts, images, and API data.
URL
The browser resolves a host and opens a connection.
Request
It sends a method, target, headers, and optional body.
PHP
The server invokes your script with request data.
Response
PHP returns a status, headers, and response body.
| Part | Request example | Response example |
|---|---|---|
| Start line | GET /courses/42 HTTP/1.1 | HTTP/1.1 200 OK |
| Headers | Accept: application/json | Content-Type: application/json |
| Body | Often empty for GET | HTML, JSON, a file, or no body |
| Meaning | What the client wants | What happened and the representation returned |
Key idea
Read the incoming request
PHP exposes web-server data through $_SERVER. Keys can vary by server, so read optional values defensively. parse_url() separates the route path from its query string.
<?php
declare(strict_types=1);
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
$accept = $_SERVER['HTTP_ACCEPT'] ?? '*/*';
echo "Method: {$method}" . PHP_EOL;
echo "Path: {$path}" . PHP_EOL;
echo "Accept: {$accept}";| Method | Typical intent | Safe/idempotent? |
|---|---|---|
GET | Read a representation | Safe and idempotent |
POST | Create or trigger processing | Usually neither |
PUT | Replace a resource | Idempotent |
PATCH | Partially update a resource | Not guaranteed |
DELETE | Remove a resource | Idempotent by intent |
Safe is not the same as secure
Build a precise response
A professional response aligns three things: its status code describes the outcome, its headers describe the body, and the body follows that declared format.
<?php
declare(strict_types=1);
header('Content-Type: application/json; charset=utf-8');
http_response_code(201);
$response = [
'data' => [
'id' => 42,
'title' => 'Learn HTTP',
],
];
echo json_encode($response, JSON_THROW_ON_ERROR);| Status | Meaning | Common use |
|---|---|---|
200 | OK | Successful read or update |
201 | Created | A new resource was created |
204 | No Content | Success with no response body |
302 | Found | Temporary redirect; use 303 after many form posts |
400 | Bad Request | Malformed or invalid request |
401 | Unauthorized | Authentication is required |
403 | Forbidden | Identity is known but not allowed |
404 | Not Found | No matching resource |
500 | Server Error | Unexpected server-side failure |
Headers must come first
<?php and decide status and headers before rendering.Web server, document root, and PHP
The web server accepts the connection, serves static files directly, and passes PHP requests to the PHP runtime. The document root is the public directory the server exposes. Application source, secrets, and writable storage should sit outside it whenever possible.
project/
├── public/ # document root
│ └── index.php # public entry point
├── src/ # application code
├── templates/ # views
├── storage/ # logs and generated files
└── vendor/ # Composer dependenciesRoute through a front controller
A front controller gives every dynamic request one entry point. It centralizes startup, error handling, sessions, middleware, and routing.
<?php
declare(strict_types=1);
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
$route = "{$method} {$path}";
match ($route) {
'GET /' => print '<h1>PHP Web Foundations</h1>',
'GET /health' => print 'OK',
default => (function (): void {
http_response_code(404);
echo '<h1>Page not found</h1>';
})(),
};Tip
Practice challenge
Add GET /api/status to the front controller. Return status 200, a JSON content type, and an object containing status and the current UTC time. Verify an unknown route still returns 404.
Recap & quick check
Key takeaways
- A PHP web app transforms one HTTP request into one HTTP response.
- Method, target, headers, and optional body describe a request.
- Status, headers, and optional body must tell one consistent response story.
- Keep private source and storage outside the public document root.
- A front controller centralizes application startup and routing.
Quick check
1. Which response part describes whether the request succeeded?
2. Which method should normally only read data?
3. Why use a public/ document root?
4. What does a front controller centralize?