symfony/http-foundation
Symfony HttpFoundation provides an object-oriented API for HTTP: requests, responses, headers, cookies, sessions, and file uploads. It normalizes PHP’s globals into consistent objects, making it easier to build and test web applications and middleware.
Installation:
composer require symfony/http-foundation
Laravel already includes this as a core dependency, so no additional installation is typically needed.
First Use Case:
Access the Request and Response objects in a Laravel controller or middleware:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
// In a controller
public function show(Request $request)
{
$method = $request->getMethod(); // 'GET', 'POST', etc.
$query = $request->query->all(); // All query parameters
return new Response('Hello World', 200, [
'Content-Type' => 'text/plain',
]);
}
Key Classes to Explore First:
Request: Parse incoming HTTP requests.Response: Construct HTTP responses.JsonResponse: For API responses.FileBag: Handle file uploads.Session: Session management.Where to Look Next:
Illuminate\Http\Request and Illuminate\Http\Response (which extend Symfony’s classes).$request = Request::createFromGlobals(); // For CLI/testing
$input = $request->request->all(); // POST/PUT/PATCH data
$headers = $request->headers->all(); // All headers
$queryParams = $request->query->get('param'); // Single query param
$routeParams = $request->attributes->get('id'); // Route params
$file = $request->files->get('file');
if ($file instanceof UploadedFile) {
$file->move($targetPath); // Save file
}
return new Response('Content', 200, [
'X-Custom-Header' => 'Value',
]);
return new JsonResponse(['data' => 'value'], 200, [], true);
return new BinaryFileResponse($filePath, 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="file.pdf"',
]);
$response = new Response();
$response->setPublic();
$response->setMaxAge(3600);
$response->setContent($stream);
return $response;
$session = new Session();
$session->start();
$session->set('key', 'value');
$session->getFlashBag()->add('success', 'Operation completed!');
$handler = new RedisSessionHandler($redisClient);
$session = new Session($handler);
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class CustomMiddleware implements Middleware
{
public function handle(Request $request, Closure $next): Response
{
// Modify request/response
$response = $next($request);
$response->headers->set('X-Processed-By', 'CustomMiddleware');
return $response;
}
}
$kernel->pushMiddleware(CustomMiddleware::class);
$request = Request::create('/path', 'GET', [], [], [], ['HTTP_AUTHORIZATION' => 'Bearer token']);
$response = $controller->handle($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertJson($response->getContent());
Leverage Laravel’s Extensions:
Laravel’s Request and Response classes extend Symfony’s, so you can use Symfony’s methods alongside Laravel’s helpers:
$request = app(Request::class);
$request->merge([ // Laravel-specific
'custom' => 'value',
]);
Custom Request Classes:
Extend Symfony\Component\HttpFoundation\Request to add domain-specific logic:
class ApiRequest extends Request
{
public function getApiVersion(): string
{
return $this->headers->get('X-API-Version', 'v1');
}
}
Response Factories: Create reusable response builders:
class ResponseFactory
{
public static function success(array $data, int $status = 200): JsonResponse
{
return new JsonResponse([
'success' => true,
'data' => $data,
], $status);
}
public static function error(string $message, int $status = 400): JsonResponse
{
return new JsonResponse([
'success' => false,
'error' => $message,
], $status);
}
}
File Upload Validation:
Use Symfony’s UploadedFile for validation:
$file = $request->file('avatar');
if ($file->isValid() && $file->getError() === UPLOAD_ERR_OK) {
$allowedTypes = ['image/jpeg', 'image/png'];
if (in_array($file->getMimeType(), $allowedTypes)) {
$file->move($storagePath);
}
}
Session Integration:
Laravel’s session uses Symfony’s Session under the hood. Customize storage or handlers:
// config/session.php
'driver' => 'redis',
'options' => [
'prefix' => 'laravel_session_',
],
API Versioning:
Use Symfony’s Request to handle API versioning:
$version = $request->headers->get('Accept-Version', 'v1');
$router->setRouteCollection($this->getRoutesForVersion($version));
CORS Handling:
Leverage Symfony’s Response for CORS:
$response = new Response($content);
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST');
return $response;
Rate Limiting:
Use Symfony’s Request to track IP-based limits:
$ip = $request->getClientIp();
$limit = RateLimiter::getInstance()->consume($ip, 'api_endpoint');
if (!$limit->isAllowed()) {
return new Response('Too many requests', 429);
}
Request Creation in CLI:
Request::createFromGlobals() won’t work in CLI (e.g., Artisan commands). Use Request::create() with manual parameters:
$request = Request::create('/path', 'GET');
Session Handling in Tests:
Session requires a storage handler. Use Laravel’s Session facade or mock it:
$session = new Session(new NullSessionStorage());
File Upload Errors:
UploadedFile::getError() returns UPLOAD_ERR_OK (0) for successful uploads. Non-zero values indicate errors (e.g., UPLOAD_ERR_INI_SIZE for file size limits).Header Case Sensitivity:
Request stores them as-is. Use get() or headers->get() for case-insensitive access:
$request->headers->get('content-type'); // Works
$request->headers->get('Content-Type'); // Also works
Query String Parsing:
Request::query->all() returns an **assHow can I help you explore Laravel packages today?