El componente HttpFoundation de Symfony encapsula las superglobales $_GET, $_POST, $_FILES, $_COOKIE y $_SERVER en objetos orientados a objetos. Puedes usarlo en cualquier proyecto PHP sin instalar Symfony completo.
Instalación
composer require symfony/http-foundation
Request::createFromGlobals()
Reemplaza todas las superglobales con un único objeto:
<?php
use SymfonyComponentHttpFoundationRequest;
$request = Request::createFromGlobals();
// Equivalente a $_GET['pagina'] ?? 1
$pagina = $request->query->getInt('pagina', 1);
// Equivalente a $_POST['email'] ?? ''
$email = $request->request->get('email', '');
// Cabecera HTTP
$accept = $request->headers->get('Accept');
// Método HTTP
echo $request->getMethod(); // GET, POST, PUT
// URL completa
echo $request->getUri();
// IP del cliente
echo $request->getClientIp();
?>
Bolsas de parámetros (ParameterBag)
Cada grupo de parámetros es una ParameterBag con métodos de acceso tipado:
<?php
$id = $request->query->getInt('id'); // ?id=5 ? 5
$token = $request->headers->get('X-Api-Token');
$file = $request->files->get('foto'); // UploadedFile
$cook = $request->cookies->get('sesion');
?>
Response
<?php
use SymfonyComponentHttpFoundationResponse;
$response = new Response(
'<h1>Hola</h1>',
Response::HTTP_OK,
['Content-Type' => 'text/html']
);
$response->send();
?>
JsonResponse
<?php use SymfonyComponentHttpFoundationJsonResponse; $data = ['usuario' => 'Ana', 'activo' => true]; $response = new JsonResponse($data, 200); // O equivalente: $response = JsonResponse::fromJsonString(json_encode($data), 200); $response->send(); ?>
RedirectResponse
<?php
use SymfonyComponentHttpFoundationRedirectResponse;
// Redirigir con 302 (por defecto)
$response = new RedirectResponse('/login');
// Redirigir con 301 (permanente)
$response = new RedirectResponse('/nueva-url', 301);
$response->send();
?>
BinaryFileResponse
Descarga de ficheros con gestión de cabeceras correcta:
<?php
use SymfonyComponentHttpFoundationBinaryFileResponse;
use SymfonyComponentHttpFoundationResponseHeaderBag;
$response = new BinaryFileResponse('/var/datos/factura.pdf');
$response->setContentDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
'factura-2024.pdf'
);
$response->prepare($request);
$response->send();
?>
BinaryFileResponse gestiona automáticamente las cabeceras ETag, Last-Modified y soporta peticiones condicionales (If-None-Match).
StreamedResponse
Cuando el contenido se genera progresivamente (exportaciones grandes, logs en tiempo real):
<?php
use SymfonyComponentHttpFoundationStreamedResponse;
$response = new StreamedResponse(function () {
$handle = fopen('php://output', 'w');
fputcsv($handle, ['id', 'nombre', 'email']);
for ($i = 1; $i <= 10000; $i++) {
fputcsv($handle, [$i, "Usuario $i", "user{$i}@ejemplo.com"]);
if ($i % 1000 === 0) {
ob_flush();
flush();
}
}
fclose($handle);
});
$response->headers->set('Content-Type', 'text/csv');
$response->headers->set('Content-Disposition', 'attachment; filename="usuarios.csv"');
$response->send();
?>
Cookies
<?php
use SymfonyComponentHttpFoundationCookie;
$cookie = Cookie::create('preferencia')
->withValue('oscuro')
->withExpires(new DateTimeImmutable('+30 days'))
->withSecure(true)
->withHttpOnly(true)
->withSameSite('Strict');
$response->headers->setCookie($cookie);
$response->send();
?>
Mini front-controller
<?php
$request = Request::createFromGlobals();
$path = $request->getPathInfo();
$method = $request->getMethod();
$response = match (true) {
$path === '/' => new Response('Inicio', 200),
$path === '/api/ping' => new JsonResponse(['ok' => true]),
default => new Response('No encontrado', 404),
};
$response->send();
?>
Errores comunes
- Headers already sent: llama a
$response->send()antes de hacer cualquierechoo tener salida en el buffer. - getInt() devuelve 0 inesperadamente: el parámetro no existe o no es numérico. Usa el segundo argumento como valor por defecto.
- BinaryFileResponse y Apache mod_xsendfile: en servidores con
X-Sendfile, llama a$response->trustXSendfileTypeHeader()para delegar la descarga al servidor web.
