DALT.PHP
Framework Deep Dive1. Entry Point

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

  1. Encapsulation: All incoming data is in one place.
  2. Immutability: We capture the state at the start of the request, preventing other code from accidentally changing global variables.
  3. Clean API: Instead of $_POST['email'] ?? null, you use $request->input('email').
  4. 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

  1. Single Point of Truth: The Request object is the only place you should look for incoming data.
  2. Method Spoofing: It automatically handles _method overrides, allowing browsers (which only support GET/POST) to perform DELETE and PATCH requests.
  3. URL Parsing: It uses parse_url to 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.


Want to see where these inputs are actually used? Next, we'll look at the Helper Functions that make accessing this data even easier.

On this page