The Request Object

The Rhapsody\Core\Request class provides an object-oriented way to interact with the current HTTP request. It encapsulates all the information about the request, such as GET and POST data, server variables, and uploaded files, making your application more secure and easier to work with.

An instance of the Request object is automatically created and passed as the first argument to every controller method by the router.


Accessing Request Information

Route Pattern Matching

The is() method allows you to check if the request's path matches a given pattern. This is particularly useful for middleware to conditionally apply logic based on the route.

The method supports a trailing wildcard (*) to match any subpath:

// Check if the current request is for the API
    if ($request->is('api/*')) {
        // API-specific handling
    }

    // Check for exact match
    if ($request->is('users')) {
        // Users page
    }

    // Check for admin routes
    if ($request->is('admin/*')) {
        // Admin routes
    }

The is() method normalizes both the request path and the pattern by stripping leading slashes, making it consistent for matching.

Get the Request Path & Method

// In a controller method
public function updateUser(Request $request, string $id): Response
{
    // Get the request method (e.g., 'get', 'post')
    $method = $request->getMethod(); // "post"

    // Get the clean URI path (e.g., '/users/1')
    $path = $request->getPath(); // "/users/1"
    
    // ...
}

Retrieving Input (GET, POST, JSON, PUT, etc.)

The getBody() method intelligently handles all input sources:

  • If the Content-Type is application/json, it decodes the JSON payload.
  • For standard form submissions (application/x-www-form-urlencoded), it returns $_POST.
  • For PUT, PATCH, or DELETE requests with form data, it parses php://input automatically.
$allInput = $request->getBody();
$email    = $allInput['email'] ?? null;

Typed Input Accessors

string(), int(), bool() and array() read a single input value and hand it back as exactly the type you asked for, so you don't need casts or isset() checks. They look in the request body first (form fields or a JSON payload, as described above) and then fall back to the query string.

$name   = $request->string('name');        // '' when missing
$page   = $request->int('page', 1);        // 1 when missing or not an integer
$active = $request->bool('active');        // false when missing
$tags   = $request->array('tags');         // [] when missing or not an array
                                           // ?tags[]=php&tags[]=twig  gives  ['php', 'twig']
Method Accepts Gives the default when
string($key, $default = '')Strings, ints, floats and bools (converted to a string)The value is missing, null, or an array
int($key, $default = 0)Ints and integer-like strings such as '42' or '-7'The value is anything else, including '1.5', '12abc', an empty string, or a decimal number
bool($key, $default = false)true/false, 1/0, and the strings true, false, on, off, yes, no (case-insensitive)The value is anything else. An empty string is read as false, not as the default
array($key)Arrays, such as tags[]=a&tags[]=b or a JSON arrayThe value is missing or not an array (it always returns []; there is no default argument)

A typical controller reads like this:

public function showUsers(Request $request): Response
{
    $page       = $request->int('page', 1);
    $sort       = $request->string('sort', 'name');
    $subscribed = $request->bool('subscribed');   // an unchecked checkbox is never submitted, so this is false
    $roles      = $request->array('roles');

    // ...
}

What the Accessors Do Not Do

  • They never throw. A bad or missing value quietly becomes the default. If a value is required, check it with the Validator and reject the request. (This is the opposite of the Config reader, which throws on a missing or wrongly-typed key. See Support Helpers.)
  • They don't validate or sanitize. int() guarantees you receive an integer, not a sensible one, so clamp or range-check values like page numbers and limits yourself. string() returns the text exactly as it was sent, without the HTML-encoding that getQueryParam() applies, so escape it on output (Twig does this automatically) and never build SQL from it.
  • They work on the Request's own data. Unlike getQueryParam(), which reads PHP's $_GET directly, these methods use the data the Request was built with. That makes them work with requests created by Request::create() in your tests (see Unit Testing).

input() and all()

The accessors above are built on input(), which returns a single raw value (body first, then the query string) or a default of your choosing. all() returns every input value at once: the query string and the request body merged, with body values winning when a key appears in both.

$value = $request->input('q', 'none');   // raw value, any type
$data  = $request->all();                // query string + body

Retrieving Individual Query Parameters

To get a value from the URL's query string (e.g., /users?page=2), use the getQueryParam() method. It includes a second argument to specify a default value if the parameter is not present.

public function showUsers(Request $request): Response
{
    $currentPage = (int) $request->getQueryParam('page', 1);
    // ...
}

All Query Parameters

Use allQueryParams() to retrieve an associative array of all GET parameters from the current request. This is useful when you need to inspect or forward the entire query string.

$params = $request->allQueryParams();
// e.g., ['page' => 2, 'sort' => 'asc', 'filter' => 'active']

Canonical URL

The getCanonicalUrl() method builds a clean, SEO‑friendly canonical URL for the current request. It automatically:

  • Detects the correct protocol (http:// or https://).
  • Uses the host from $_SERVER['HTTP_HOST'].
  • Strips the path to its bare structure (no extra text).
  • Retains only allowed query parameters (by default, only page is kept).

This method is used internally by the main layout to generate the <link rel="canonical"> tag, but you can also call it manually if you need the value elsewhere.

// Keep only 'page' and 'category' in the canonical URL
$canonical = $request->getCanonicalUrl(['page', 'category']);

Retrieving Uploaded Files

You can access information about uploaded files using the getFiles() method, which returns the contents of the $_FILES superglobal.

public function handleUpload(Request $request): Response
{
    $files = $request->getFiles();
    $avatar = $files['avatar'] ?? null;
    
    if ($avatar && $avatar['error'] === UPLOAD_ERR_OK) {
        // Process the uploaded file
    }
    
    // ...
}

Direct Access to Raw Data

If you need to access raw GET or POST values directly, you can use the get() and post() methods:

$userId = $request->get('user_id');   // from $_GET
$email  = $request->post('email');    // from $_POST