HTTP Responses
Creando Respuestas
Cadenas y Arreglos
Todas las rutas y controladores deben devolver una respuesta para ser enviada de vuelta al navegador del usuario. Laravel proporciona varias formas diferentes de devolver respuestas. La respuesta más básica es devolver una cadena desde una ruta o controlador. El framework convertirá automáticamente la cadena en una respuesta HTTP completa:
Route::get('/', function () {
return 'Hello World';
});
Además de devolver cadenas desde tus rutas y controladores, también puedes devolver arreglos. El framework convertirá automáticamente el arreglo en una respuesta JSON:
Route::get('/', function () {
return [1, 2, 3];
});
¿Sabías que también puedes devolver colecciones de Eloquent desde tus rutas o controladores? Se convertirán automáticamente a JSON. ¡Inténtalo!
Objetos de Respuesta
Normalmente, no solo devolverás cadenas simples o arreglos desde tus acciones de ruta. En su lugar, devolverás instancias completas de Illuminate\Http\Response
o vistas.
Devolver una instancia completa de Response
te permite personalizar el código de estado HTTP y los encabezados de la respuesta. Una instancia de Response
hereda de la clase Symfony\Component\HttpFoundation\Response
, que proporciona una variedad de métodos para construir respuestas HTTP:
Route::get('/home', function () {
return response('Hello World', 200)
->header('Content-Type', 'text/plain');
});
Modelos y Colecciones de Eloquent
También puedes devolver modelos y colecciones de Eloquent ORM directamente desde tus rutas y controladores. Cuando lo hagas, Laravel convertirá automáticamente los modelos y colecciones en respuestas JSON respetando los atributos ocultos del modelo:
use App\Models\User;
Route::get('/user/{user}', function (User $user) {
return $user;
});
Adjuntando Encabezados a las Respuestas
Ten en cuenta que la mayoría de los métodos de respuesta son encadenables, lo que permite la construcción fluida de instancias de respuesta. Por ejemplo, puedes usar el método header
para agregar una serie de encabezados a la respuesta antes de enviarla al usuario:
return response($content)
->header('Content-Type', $type)
->header('X-Header-One', 'Header Value')
->header('X-Header-Two', 'Header Value');
O, puedes usar el método withHeaders
para especificar una matriz de encabezados que se agregarán a la respuesta:
return response($content)
->withHeaders([
'Content-Type' => $type,
'X-Header-One' => 'Header Value',
'X-Header-Two' => 'Header Value',
]);
Middleware de Control de Caché
Laravel incluye un middleware cache.headers
, que puede usarse para establecer rápidamente el encabezado Cache-Control
para un grupo de rutas. Las directivas deben proporcionarse utilizando el equivalente en «snake case» de la directiva cache-control
correspondiente y deben estar separadas por un punto y coma. Si etag
se especifica en la lista de directivas, un hash MD5 del contenido de la respuesta se establecerá automáticamente como el identificador ETag:
Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {
Route::get('/privacy', function () {
// ...
});
Route::get('/terms', function () {
// ...
});
});
Adjuntando Cookies a las Respuestas
Puedes adjuntar una cookie a una instancia de Illuminate\Http\Response
saliente usando el método cookie
. Debes pasar el nombre, el valor y el número de minutos que la cookie debe considerarse válida a este método:
return response('Hello World')->cookie(
'name', 'value', $minutes
);
El método cookie
también acepta algunos argumentos más que se usan con menos frecuencia. Generalmente, estos argumentos tienen el mismo propósito y significado que los argumentos que se darían al método nativo setcookie
de PHP:
return response('Hello World')->cookie(
'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
);
Si deseas asegurarte de que una cookie se envíe con la respuesta saliente pero aún no tienes una instancia de esa respuesta, puedes usar el facade Cookie
para «poner en cola» cookies para adjuntarlas a la respuesta cuando se envíe. El método queue
acepta los argumentos necesarios para crear una instancia de cookie. Estas cookies se adjuntarán a la respuesta saliente antes de que se envíe al navegador:
use Illuminate\Support\Facades\Cookie;
Cookie::queue('name', 'value', $minutes);
Generando Instancias de Cookie
Si deseas generar una instancia de Symfony\Component\HttpFoundation\Cookie
que pueda adjuntarse a una instancia de respuesta en un momento posterior, puedes usar el helper global cookie
. Esta cookie no se enviará de vuelta al cliente a menos que se adjunte a una instancia de respuesta:
$cookie = cookie('name', 'value', $minutes);
return response('Hello World')->cookie($cookie);
Expirando Cookies Tempranamente
Puedes eliminar una cookie expirándola mediante el método withoutCookie
de una respuesta saliente:
return response('Hello World')->withoutCookie('name');
Si aún no tienes una instancia de la respuesta saliente, puedes usar el método expire
del facade Cookie
para expirar una cookie:
Cookie::expire('name');
Cookies y Encriptación
Por defecto, gracias al middleware Illuminate\Cookie\Middleware\EncryptCookies
, todas las cookies generadas por Laravel están encriptadas y firmadas para que no puedan ser modificadas o leídas por el cliente. Si deseas desactivar la encriptación para un subconjunto de cookies generadas por tu aplicación, puedes usar el método encryptCookies
en el archivo bootstrap/app.php
de tu aplicación:
->withMiddleware(function (Middleware $middleware) {
$middleware->encryptCookies(except: [
'cookie_name',
]);
})
Redirecciones
Las respuestas de redirección son instancias de la clase Illuminate\Http\RedirectResponse
, y contienen los encabezados adecuados necesarios para redirigir al usuario a otra URL. Hay varias formas de generar una instancia de RedirectResponse
. El método más simple es usar el helper global redirect
:
Route::get('/dashboard', function () {
return redirect('/home/dashboard');
});
A veces puedes desear redirigir al usuario a su ubicación anterior, como cuando un formulario enviado no es válido. Puedes hacerlo usando la función helper global back
. Dado que esta característica utiliza la sesión, asegúrate de que la ruta que llama a la función back
esté usando el grupo de middleware web
:
Route::post('/user/profile', function () {
// Validar la solicitud...
return back()->withInput();
});
Redirigiendo a Rutas Nombradas
Cuando llamas al helper redirect
sin parámetros, se devuelve una instancia de Illuminate\Routing\Redirector
, lo que te permite llamar a cualquier método en la instancia de Redirector
. Por ejemplo, para generar una RedirectResponse
a una ruta nombrada, puedes usar el método route
:
return redirect()->route('login');
Si tu ruta tiene parámetros, puedes pasarlos como el segundo argumento al método route
:
// Para una ruta con la siguiente URI: /profile/{id}
return redirect()->route('profile', ['id' => 1]);
Rellenando Parámetros a través de Modelos Eloquent
Si estás redirigiendo a una ruta con un parámetro «ID» que se está rellenando desde un modelo Eloquent, puedes pasar el modelo en sí. El ID se extraerá automáticamente:
// Para una ruta con la siguiente URI: /profile/{id}
return redirect()->route('profile', [$user]);
Si deseas personalizar el valor que se coloca en el parámetro de la ruta, puedes especificar la columna en la definición del parámetro de la ruta (/profile/{id:slug}
) o puedes sobrescribir el método getRouteKey
en tu modelo Eloquent:
/**
* Obtener el valor de la clave de ruta del modelo.
*/
public function getRouteKey(): mixed
{
return $this->slug;
}
Redirigiendo a Acciones de Controlador
También puedes generar redirecciones a acciones de controlador. Para hacerlo, pasa el nombre del controlador y la acción al método action
:
use App\Http\Controllers\UserController;
return redirect()->action([UserController::class, 'index']);
Si la ruta de tu controlador requiere parámetros, puedes pasarlos como el segundo argumento al método action
:
return redirect()->action(
[UserController::class, 'profile'], ['id' => 1]
);
Redirigiendo a Dominios Externos
A veces puedes necesitar redirigir a un dominio fuera de tu aplicación. Puedes hacerlo llamando al método away
, que crea una RedirectResponse
sin ninguna codificación de URL adicional, validación o verificación:
return redirect()->away('https://www.google.com');
Redirigiendo con Datos de Sesión Flasheados
Redirigir a una nueva URL y flashear datos a la sesión generalmente se hacen al mismo tiempo. Normalmente, esto se hace después de realizar una acción con éxito cuando flasheas un mensaje de éxito a la sesión. Para mayor comodidad, puedes crear una instancia de RedirectResponse
y flashear datos a la sesión en una sola cadena de métodos fluida:
Route::post('/user/profile', function () {
// ...
return redirect('/dashboard')->with('status', 'Profile updated!');
});
Después de que el usuario sea redirigido, puedes mostrar el mensaje flasheado desde la sesión. Por ejemplo, usando la sintaxis de Blade:
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
Redirigiendo con Entrada
Puedes usar el método withInput
proporcionado por la instancia de RedirectResponse
para flashear los datos de entrada de la solicitud actual a la sesión antes de redirigir al usuario a una nueva ubicación. Esto se hace típicamente si el usuario ha encontrado un error de validación. Una vez que la entrada ha sido flasheada a la sesión, puedes recuperarla fácilmente durante la siguiente solicitud para repoblar el formulario:
return back()->withInput();
Otros Tipos de Respuesta
El helper response
puede usarse para generar otros tipos de instancias de respuesta. Cuando se llama al helper response
sin argumentos, se devuelve una implementación del contrato Illuminate\Contracts\Routing\ResponseFactory
. Este contrato proporciona varios métodos útiles para generar respuestas.
Respuestas de Vista
Si necesitas control sobre el estado y los encabezados de la respuesta pero también necesitas devolver una vista como contenido de la respuesta, debes usar el método view
:
return response()
->view('hello', $data, 200)
->header('Content-Type', $type);
Por supuesto, si no necesitas pasar un código de estado HTTP personalizado o encabezados personalizados, puedes usar la función helper global view
.
Respuestas JSON
El método json
establecerá automáticamente el encabezado Content-Type
a application/json
, así como convertir la matriz dada a JSON usando la función json_encode
de PHP:
return response()->json([
'name' => 'Abigail',
'state' => 'CA',
]);
Si deseas crear una respuesta JSONP, puedes usar el método json
en combinación con el método withCallback
:
return response()
->json(['name' => 'Abigail', 'state' => 'CA'])
->withCallback($request->input('callback'));
Descargas de Archivos
El método download
puede usarse para generar una respuesta que obligue al navegador del usuario a descargar el archivo en la ruta dada. El método download
acepta un nombre de archivo como segundo argumento del método, que determinará el nombre del archivo que verá el usuario al descargar el archivo. Finalmente, puedes pasar una matriz de encabezados HTTP como el tercer argumento del método:
return response()->download($pathToFile);
return response()->download($pathToFile, $name, $headers);
Symfony HttpFoundation, que gestiona las descargas de archivos, requiere que el archivo que se está descargando tenga un nombre de archivo ASCII.
Respuestas de Archivos
El método file
puede usarse para mostrar un archivo, como una imagen o PDF, directamente en el navegador del usuario en lugar de iniciar una descarga. Este método acepta la ruta absoluta al archivo como su primer argumento y una matriz de encabezados como su segundo argumento:
return response()->file($pathToFile);
return response()->file($pathToFile, $headers);
Respuestas Transmitidas
Al transmitir datos al cliente a medida que se generan, puedes reducir significativamente el uso de memoria y mejorar el rendimiento, especialmente para respuestas muy grandes. Las respuestas transmitidas permiten que el cliente comience a procesar datos antes de que el servidor haya terminado de enviarlos:
function streamedContent(): Generator {
yield 'Hello, ';
yield 'World!';
}
Route::get('/stream', function () {
return response()->stream(function (): void {
foreach (streamedContent() as $chunk) {
echo $chunk;
ob_flush();
flush();
sleep(2); // Simular retraso entre fragmentos...
}
}, 200, ['X-Accel-Buffering' => 'no']);
});
Internamente, Laravel utiliza la funcionalidad de almacenamiento en búfer de salida de PHP. Como puedes ver en el ejemplo anterior, debes usar las funciones ob_flush
y flush
para enviar contenido almacenado en búfer al cliente.
Respuestas JSON Transmitidas
Si necesitas transmitir datos JSON de manera incremental, puedes utilizar el método streamJson
. Este método es especialmente útil para conjuntos de datos grandes que necesitan ser enviados progresivamente al navegador en un formato que pueda ser fácilmente analizado por JavaScript:
use App\Models\User;
Route::get('/users.json', function () {
return response()->streamJson([
'users' => User::cursor(),
]);
});
Descargas Transmitidas
A veces puedes desear convertir la respuesta de cadena de una operación dada en una respuesta descargable sin tener que escribir el contenido de la operación en el disco. Puedes usar el método streamDownload
en este escenario. Este método acepta un callback, un nombre de archivo y una matriz opcional de encabezados como sus argumentos:
use App\Services\GitHub;
return response()->streamDownload(function () {
echo GitHub::api('repo')
->contents()
->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme.md');
Macros de Respuesta
Si deseas definir una respuesta personalizada que puedas reutilizar en varias de tus rutas y controladores, puedes usar el método macro
en el facade Response
. Normalmente, debes llamar a este método desde el método boot
de uno de los proveedores de servicios de tu aplicación, como el proveedor de servicios App\Providers\AppServiceProvider
:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Inicializar cualquier servicio de la aplicación.
*/
public function boot(): void
{
Response::macro('caps', function (string $value) {
return Response::make(strtoupper($value));
});
}
}
La función macro
acepta un nombre como su primer argumento y un closure como su segundo argumento. El closure del macro se ejecutará al llamar al nombre del macro desde una implementación de ResponseFactory
o el helper response
:
return response()->caps('foo');