ZeroPHP

Request & Response

Request & Response

The HTTP layer lives at:

Controllers may return strings, arrays, models, iterables, or explicit Response objects; the router normalises everything through Response::resolve().


Request

The router calls Request::capture() once per request and injects the same instance into your controllers (where it's also available type-hinted on action signatures). You can also reach it from anywhere via Request::instance() or the global request() helper.

Lifecycle

Request::capture(): self

Snapshot the current PHP request. Called by the router; you generally don't call this yourself.

use Zero\Lib\Http\Request;

$request = Request::capture(); // singleton-like; subsequent calls return the same instance

Request::instance(): self

Return the current request without re-capturing.

$request = Request::instance();

Request::replace(array $overrides): self

Replace the current request (mainly for tests).

Request::replace([
    'method' => 'POST',
    'uri'    => '/users',
    'input'  => ['email' => 'a@b.test'],
]);

Input

->all(): array

All input — query + form + JSON merged.

$data = $request->all();

->input(string $key, mixed $default = null): mixed

Read a single input value.

$email = $request->input('email');
$page  = $request->input('page', 1);

->has(string $key): bool

if ($request->has('email')) { /* ... */ }

->json(?string $key = null, mixed $default = null): ?array

JSON-decoded body (or a single key).

$payload = $request->json();
$first   = $request->json('items.0');

Validation

->validate(array $rules, array $messages = [], array $attributes = []): array

Validate input. Throws Zero\Lib\Validation\ValidationException on failure (handled by the global error handler).

$data = $request->validate([
    'email'    => 'required|email',
    'password' => 'required|min:8',
]);

Headers

->header(?string $key = null, mixed $default = null): mixed

Pass null to get the full header bag.

$ua = $request->header('User-Agent');
$all = $request->header(); // ['user-agent' => '...', ...]

->expectsJson(): bool

True when the client Accepts JSON.

return $request->expectsJson()
    ? Response::json($data)
    : view('users.show', ['user' => $data]);

->wantsJson(): bool

Stricter alias of expectsJson() ignoring */*.

if ($request->wantsJson()) { /* ... */ }

Cookies

->cookie(string $key, mixed $default = null): mixed

$theme = $request->cookie('theme', 'light');

->cookies(): array

$all = $request->cookies();

Files

->file(string $key, mixed $default = null): mixed

Returns an UploadedFile (or null).

$avatar = $request->file('avatar');
$path   = $avatar?->store('avatars');

->files(): array

$uploads = $request->files();

Server / metadata

->method(): string

$method = $request->method(); // 'POST'

->path(): string

$request->path(); // '/users/42'

->uri(): string

Path + query string.

$request->uri(); // '/users/42?tab=info'

->root(): string

Scheme + host (no path).

$request->root(); // 'https://api.example.com'

->fullUrl(): string

$request->fullUrl(); // 'https://api.example.com/users/42?tab=info'

->ip(): ?string

$ip = $request->ip();

->getContent(): string

Raw request body.

$raw = $request->getContent();

Attributes (middleware ↔ controller)

Attributes let middleware stash work for downstream code. Backed by static state on Request.

Request::set(string $key, mixed $value): void

// In middleware
Request::set('user', Auth::user());

Request::get(string $key, mixed $default = null): mixed

// In a controller
$user = Request::get('user');

->attribute(string $key, mixed $default = null): mixed

Instance-level read.

$user = $request->attribute('user');

->attributes(): array

$bag = $request->attributes();

Session

->session(?string $key = null, mixed $default = null): mixed

Read the session via the request.

$flash = $request->session('flash.success');
$all   = $request->session(); // raw $_SESSION

Property access

$request->key and isset($request->key) proxy to attributes/input — convenient inside controllers:

$email = $request->email; // sugar for $request->input('email')

Response

Static factories build a Response, which the router sends. You can also return raw scalars/arrays/models from controllers — Response::resolve() wraps them.

Builders

Response::make(mixed $content = '', int $status = 200, array $headers = []): static

Generic constructor.

return Response::make('OK', 200, ['X-Robots-Tag' => 'noindex']);

Response::json(mixed $data, int $status = 200, array $headers = []): static

return Response::json(['ok' => true]);
return Response::json($users, 200, ['X-Total' => count($users)]);

Response::text(string $text, int $status = 200, array $headers = []): static

return Response::text('pong');

Response::html(string $html, int $status = 200, array $headers = []): static

return Response::html('<h1>Hello</h1>');

Response::xml(string $xml, int $status = 200, array $headers = []): static

return Response::xml('<?xml version="1.0"?><root/>');

Response::api(string $status, mixed $payload = null, int $statusCode = 200, array $headers = []): static

Opinionated {status, message, data} envelope.

return Response::api('success', $user);
return Response::api('error', null, 422, ['X-Error' => 'validation']);

Redirects

Response::redirect(string $location, int $status = 302, array $headers = []): static

return Response::redirect('/login');

Response::redirectRoute(string $name, array $parameters = [], bool $absolute = true, int $status = 302, array $headers = []): static

return Response::redirectRoute('users.show', ['id' => $user->id]);

Response::redirectBack(string $fallback = '/', int $status = 302, array $headers = []): static

return Response::redirectBack('/dashboard');

Streams & files

Response::stream(callable|string $stream, int $status = 200, array $headers = [], string $contentType = 'text/event-stream'): static

return Response::stream(function () {
    foreach (stream_events() as $event) {
        echo "data: " . json_encode($event) . "\n\n";
        ob_flush(); flush();
    }
});

Response::file(string $path, array $headers = [], ?string $name = null, string $disposition = 'inline'): static

return Response::file(storage_path('exports/users.csv'), [], 'users.csv', 'attachment');

Empty / pass-through

Response::noContent(int $status = 204, array $headers = []): static

return Response::noContent();

Response::resolve(mixed $value): static

Normalize any controller return value to a Response. Used by the router.

$response = Response::resolve($controllerReturn);

Mutators

These chain on a Response instance:

->status(int $status): self

return Response::json($data)->status(201);

->withHeaders(array $headers): self

return Response::json($data)->withHeaders(['X-Total' => 42]);

->getStatus(): int

$response->getStatus(); // 200

->send(): void

Emit headers + body. The router calls this for you.

$response->send();

Global helpers

These are thin wrappers around Response::* and Request::* defined in core/libraries/Support/Helper.php. See helpers.md for the full list.

return view('users.show', ['user' => $user]);     // Response::html
return response($payload, 201);                    // auto-detects type
return redirect('/login');                         // Response::redirect
return back();                                     // Response::redirectBack

$email = request('email');                         // Request::get
$user  = auth();                                   // current user

On this page

Request & ResponseRequestLifecycleRequest::capture(): selfRequest::instance(): selfRequest::replace(array $overrides): selfInput->all(): array->input(string $key, mixed $default = null): mixed->has(string $key): bool->json(?string $key = null, mixed $default = null): ?arrayValidation->validate(array $rules, array $messages = [], array $attributes = []): arrayHeaders->header(?string $key = null, mixed $default = null): mixed->expectsJson(): bool->wantsJson(): boolCookies->cookie(string $key, mixed $default = null): mixed->cookies(): arrayFiles->file(string $key, mixed $default = null): mixed->files(): arrayServer / metadata->method(): string->path(): string->uri(): string->root(): string->fullUrl(): string->ip(): ?string->getContent(): stringAttributes (middleware ↔ controller)Request::set(string $key, mixed $value): voidRequest::get(string $key, mixed $default = null): mixed->attribute(string $key, mixed $default = null): mixed->attributes(): arraySession->session(?string $key = null, mixed $default = null): mixedProperty accessResponseBuildersResponse::make(mixed $content = '', int $status = 200, array $headers = []): staticResponse::json(mixed $data, int $status = 200, array $headers = []): staticResponse::text(string $text, int $status = 200, array $headers = []): staticResponse::html(string $html, int $status = 200, array $headers = []): staticResponse::xml(string $xml, int $status = 200, array $headers = []): staticResponse::api(string $status, mixed $payload = null, int $statusCode = 200, array $headers = []): staticRedirectsResponse::redirect(string $location, int $status = 302, array $headers = []): staticResponse::redirectRoute(string $name, array $parameters = [], bool $absolute = true, int $status = 302, array $headers = []): staticResponse::redirectBack(string $fallback = '/', int $status = 302, array $headers = []): staticStreams & filesResponse::stream(callable|string $stream, int $status = 200, array $headers = [], string $contentType = 'text/event-stream'): staticResponse::file(string $path, array $headers = [], ?string $name = null, string $disposition = 'inline'): staticEmpty / pass-throughResponse::noContent(int $status = 204, array $headers = []): staticResponse::resolve(mixed $value): staticMutators->status(int $status): self->withHeaders(array $headers): self->getStatus(): int->send(): voidGlobal helpers