ez-php / http
HTTP message objects for the ez-php framework — immutable Request, Response, RequestFactory, and ResponseEmitter. Zero dependencies.
Requires
- php: ^8.5
Requires (Dev)
- ez-php/docker: ^2.0
- ez-php/testing-application: ^2.0
- friendsofphp/php-cs-fixer: ^3.94
- phpstan/phpstan: ^2.1
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^13.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 2.5.6
- 2.5.5
- 2.5.4
- 2.5.3
- 2.5.2
- 2.5.1
- 2.5.0
- 2.4.11
- 2.4.10
- 2.4.9
- 2.4.8
- 2.4.7
- 2.4.6
- 2.4.5
- 2.4.4
- 2.4.3
- 2.4.2
- 2.4.1
- 2.4.0
- 2.3.9
- 2.3.8
- 2.3.7
- 2.3.6
- 2.3.5
- 2.3.4
- 2.3.3
- 2.3.2
- 2.3.1
- 2.3.0
- 2.2.1
- 2.2.0
- 2.1.1
- 2.1.0
- 2.0.1
- 2.0.0
- 1.14.0
- 1.13.1
- 1.13.0
- 1.12.2
- 1.12.1
- 1.12.0
- 1.11.2
- 1.11.1
- 1.11.0
- 1.10.0
- 1.9.2
- 1.9.1
- 1.9.0
- 1.8.0
- 1.7.1
- 1.7.0
- 1.6.1
- 1.6.0
- 1.5.1
- 1.5.0
- 1.4.2
- 1.4.1
- 1.4.0
- 1.3.0
- 1.2.0
- 1.1.1
- 1.1.0
- 1.0.1
- 1.0.0
- 0.9.3
- 0.9.2
- 0.9.1
- 0.9.0
- 0.8.6
- 0.8.5
- 0.8.4
- 0.8.3
- 0.8.2
- 0.8.1
- 0.8.0
- 0.7.1
- 0.7.0
- 0.6.2
- 0.6.1
- 0.6.0
- 0.5.3
- 0.5.2
- 0.5.1
- 0.5.0
- 0.4.1
- 0.4.0
- 0.3.0
- 0.2.0
- 0.1.0
This package is auto-updated.
Last update: 2026-09-30 19:50:23 UTC
README
HTTP message objects for PHP — immutable Request, Response, RequestFactory, ResponseFactory, StreamedResponse, ResponseEmitter, Cookie, and UploadedFile. Zero dependencies.
Requirements
- PHP 8.5+
Installation
composer require ez-php/http
Usage
Request
use EzPhp\Http\Request; use EzPhp\Http\RequestFactory; // Create from PHP globals (web context) $request = RequestFactory::createFromGlobals(); echo $request->method(); // GET, POST, ... echo $request->uri(); // /users/42 echo $request->query('page'); // query string value echo $request->input('name'); // POST body value // Strict typed body values — null unless the value is exactly that type $qty = $request->integer('qty'); // 3 or "3" → 3; "3abc", 3.0, true → null $gift = $request->boolean('gift'); // true/false, "true"/"false"/"1"/"0", 1/0; else null $price = $request->decimal('price', scale: 2); // "19.9" → "19.90"; "19.999" → null (never rounded) echo $request->header('accept'); // request header (case-insensitive) echo $request->cookie('session'); // cookie value echo $request->param('id'); // route parameter (set by router) echo $request->rawBody(); // raw request body string echo $request->ip(['10.0.0.1']); // client IP; X-Forwarded-For honoured only from the listed trusted proxies // Uploaded files $file = $request->file('avatar'); // returns UploadedFile|null // Immutable — returns a new instance $request = $request->withMethod('PATCH'); $request = $request->withParams(['id' => '42']);
Response
use EzPhp\Http\Response; use EzPhp\Http\ResponseEmitter; use EzPhp\Http\ResponseFactory; $response = new Response(body: 'Hello', status: 200); // Fluent header chaining — each call returns a new instance $response = $response ->withHeader('Content-Type', 'application/json') ->withHeader('X-Request-Id', 'abc123'); // Factory helpers $json = ResponseFactory::json(['id' => 1]); $redirect = ResponseFactory::redirect('/dashboard'); $html = ResponseFactory::html('<h1>Hello</h1>'); // Send to the browser (new ResponseEmitter())->emit($response);
emit() accepts any ResponseInterface, including StreamedResponse. Inside an ez-php
application use $app->send($request, $response) instead: it reports stream failures and
runs terminable middleware after the body has been sent.
Streamed responses
use EzPhp\Http\Sse\SseEvent; use EzPhp\Http\StreamedResponse; // File download — the resource is read in chunks and closed afterwards $download = StreamedResponse::download($storage->getStream('reports/q3.csv'), 'q3.csv', $size, 'text/csv'); // Server-Sent Events $events = StreamedResponse::sse(function (): \Generator { yield new SseEvent(json_encode(['progress' => 50], JSON_THROW_ON_ERROR), 'progress'); });
Headers are sent before the first chunk, so an exception inside the generator can no longer become
an error page. Check authorisation and inputs before returning a StreamedResponse.
Cookie
use EzPhp\Http\Cookie; $cookie = new Cookie( name: 'session', value: 'abc123', expires: time() + 3600, path: '/', secure: true, httpOnly: true, sameSite: 'Lax', ); $response = $response->withHeader('Set-Cookie', $cookie->toHeaderValue());
UploadedFile
use EzPhp\Http\UploadedFile; $file = $request->file('avatar'); // returns UploadedFile|null if ($file !== null && $file->isValid()) { $file->moveTo('/var/www/uploads/' . basename($file->originalName())); echo $file->mimeType(); // 'image/jpeg' (client-reported, not verified) echo $file->size(); // bytes }
Classes
| Class | Description |
|---|---|
RequestInterface |
Contract for the Request value object |
Request |
Immutable HTTP request value object (final readonly class) |
RequestFactory |
Builds a Request from PHP superglobals |
Response |
HTTP response value object; clone-based withHeader() (case-insensitive replace) |
Headers |
Headers::get($response->headers(), 'content-type') — case-insensitive lookup; set()/normalize() used by both responses |
ResponseFactory |
Static helpers: json(), redirect(), html(), text(), noContent() |
ResponseEmitter |
Sends any ResponseInterface — headers via HeaderSenderInterface, body via OutputInterface, chunk by chunk for streams |
HeaderSenderInterface |
Abstraction over header() calls (injectable for testing) |
NativeHeaderSender |
Default HeaderSenderInterface implementation using PHP's header() |
Cookie |
Immutable value object for Set-Cookie attributes; toHeaderValue() produces the header string |
UploadedFile |
Wraps a $_FILES entry; isValid(), moveTo(), originalName(), mimeType(), size(), error() |
License
MIT — Andreas Uretschnig