The Request Object
How DALT captures and wraps global PHP states into a clean, testable object
In raw PHP, you're used to reaching for "superglobals" like $_GET, $_POST, and $_SERVER. While these work, they are global, uncontrolled, and hard to test.
DALT wraps these into the Request object (Core\Request).
Why We Use a Request Object
- Encapsulation: All incoming data is in one place.
- Immutability: We capture the state at the start of the request, preventing other code from accidentally changing global variables.
- Clean API: Instead of
$_POST['email'] ?? null, you use$request->input('email'). - Testability: In a unit test, we can "fake" a request by creating an instance of this class manually.
1. Capturing the Request
In public/index.php, the very first thing we do is capture the current environment:
$request = Core\Request::capture();Inside the Request class, the capture() method is a static factory:
// framework/Core/Request.php
public static function capture(): static
{
// Greedily grab all PHP superglobals
return new static($_GET, $_POST, $_SERVER);
}Wait, what is static()? It tells PHP to create an instance of whatever class this method is being called on (useful if you ever sub-class the Request).
2. Accessing Input Data
The Request object provides individual methods to reach into the captured data.
URL Query Parameters (?id=1)
public function query($key = null, $default = null)
{
if ($key === null) {
return $this->query; // Return all ? parameters
}
return $this->query[$key] ?? $default;
}Form Input (POST data)
public function input($key = null, $default = null)
{
if ($key === null) {
return $this->input; // Return all POST parameters
}
return $this->input[$key] ?? $default;
}3. Detecting Methods & Paths
The Request object is also responsible for telling the Router where we are and how we got here.
public function method(): string
{
// Check for spoofed methods like _method=DELETE
return strtoupper($this->input['_method'] ?? $this->server['REQUEST_METHOD'] ?? 'GET');
}
public function path(): string
{
$path = parse_url($this->server['REQUEST_URI'] ?? '/', PHP_URL_PATH);
return $path ?: '/';
}Key Takeaways
- Single Point of Truth: The Request object is the only place you should look for incoming data.
- Method Spoofing: It automatically handles
_methodoverrides, allowing browsers (which only support GET/POST) to perform DELETE and PATCH requests. - URL Parsing: It uses
parse_urlto strip away query strings from the path so the router doesn't get confused.
What's Good Here
✅ Replaces messy superglobals with a clean, object-oriented API
✅ Decouples your application logic from the global PHP environment
✅ Simple implementation (under 70 lines) that covers 99% of use cases
✅ Intentionally minimal - easy to understand and extend yourself
Design Note
File uploads ($_FILES) and header parsing are intentionally not included. This keeps the code simple and teachable. If you need these features, you can add them yourself or use a production framework like Laravel.
Navigation
Want to see where these inputs are actually used? Next, we'll look at the Helper Functions that make accessing this data even easier.