Repository navigation
Input
Pair\Http\Input is the immutable request input object used by the explicit Pair v4 web controller path.
It gives controllers one small object for:
- HTTP method
- query-string values
- form or JSON body values
- normalized request headers
- merged typed accessors
Use Request for JSON API modules that extend Pair\Api\ApiController.
Use Input for web modules that extend Pair\Web\Controller.
use Pair\Http\Input;
$input = new Input(
'post',
['status' => 'draft', 'page' => '2'],
['status' => 'published', 'featured' => 'true'],
['content-type' => 'application/json']
);
$input->method(); // POST
$input->query('status'); // draft
$input->body('status'); // published
$input->string('status'); // published
$input->int('page'); // 2
$input->bool('featured'); // true
$input->header('Content-Type'); // application/jsonMerged accessors read from query + body, with body values taking precedence.
Input::fromGlobals() reads $_SERVER, $_GET, and $_POST.
When there is no $_POST payload and the request advertises application/json, it parses the raw JSON body into the body array.
use Pair\Http\Input;
$input = Input::fromGlobals();
if ($input->method() === 'PATCH') {
$changes = $input->only(['name', 'email', 'isActive']);
}Invalid or empty JSON bodies are treated as an empty body array. The object does not store validation errors; validate at the controller or form layer.
JSON scalars and null also become an empty body array. A JSON object or list is accepted as an array. To supply a raw body in a test, use Input::fromGlobals($rawBody); the content-type check and precedence of non-empty $_POST still apply.
use Pair\Web\Controller;
use Pair\Web\PageResponse;
require_once __DIR__ . '/classes/OrdersDefaultPageState.php';
/**
* Orders module controller using the explicit Pair v4 request path.
*/
final class OrdersController extends Controller {
/**
* Render the list page with typed query-string state.
*/
public function defaultAction(): PageResponse {
$input = $this->input();
$state = new OrdersDefaultPageState(
status: $input->string('status', 'open'),
page: max(1, $input->int('page', 1))
);
return $this->page('default', $state, 'Orders');
}
}$search = $input->string('search', '');
$page = $input->int('page', 1);
$active = $input->bool('active');
$tags = $input->array('tags');
$hasSort = $input->has('sort');
$slice = $input->only(['search', 'page', 'sort']);string(), int(), and bool() return the provided default when the merged value is a composite value such as an array or a non-stringable object.
This avoids ambiguous scalar casts for malformed query or body data such as ?search[]=term.
has() returns true for explicitly present falsy values such as 0, false, and ''.
It returns false only when the merged value is null.
Typed accessors convert values; they are not validators or HTML escaping helpers.
| Accessor | Current behavior |
|---|---|
string() |
Casts scalar and Stringable values; falls back for null, arrays, and other objects. An empty string remains an empty string. |
int() |
Falls back for null, '', and non-scalars; otherwise applies a PHP integer cast. A non-numeric string such as abc becomes 0, even if another default was supplied. |
bool() |
Trims and lowercases scalar or Stringable values. Accepts 1, true, yes, on and 0, false, no, off; unrecognized values return the default. |
array() |
Returns arrays unchanged, uses the default for null, and wraps any other value in a one-element array. |
only() |
Selects non-null merged values by name; it does not cast or validate them. |
For a value that must come specifically from the URL, read query() rather than a merged accessor. Body fields can override query values, including with null. Apply domain checks before persistence and escape values when rendering HTML.
-
method()always returns uppercase. -
fromGlobals()normalizes header names to lowercase. When calling the constructor directly, supply lowercase header keys yourself. -
header()lowercases the lookup name, so lookups are case-insensitive when the stored keys are normalized. -
query(),body(), andvalue()return the full array when called without a key. -
Inputis immutable; create a new object if tests or adapters need a different request shape.
See also: Controller, PageResponse, Request, API.
Home · Setup · Configuration
Build with Pair 4
- Generator
- Controllers and responses
- Read models
- ActiveRecord and queries
- Forms and validation
- PairUI.js and HTML fragments
APIs and authentication
- API guide and CRUD
- Middleware and rate limits
- Users, sessions, and ACL
- Passkeys and social login
- Native mobile setup
Integrate and operate
- Integrations
- Runtime extensions and adapter keys
- Cache and cache stores
- Logs and observability
- PWA and push
- Packages and distribution
- Upgrade to v4