Respostes HTTP

Com crear respostes a Laravel: vistes, JSON, redirects, descàrregues i headers personalitzats.

Respostes bàsiques#

Laravel converteix automàticament el que retornes des d'una ruta o controlador en una resposta HTTP adequada. Si retornes un string, Laravel el converteix en una resposta amb el Content-Type text/html. Si retornes un array o un model Eloquent, el converteix automàticament en JSON. Aquesta conversió automàtica fa que escriure respostes sigui molt natural:

// String: Laravel crea una resposta text/html
Route::get('/hola', function () {
    return 'Hola, món!';
});
 
// Vista Blade: Laravel renderitza el template i retorna HTML
Route::get('/', function () {
    return view('welcome');
});
 
// Array o col·lecció: Laravel serialitza a JSON automàticament
Route::get('/api/usuaris', function () {
    return User::all();
});

Quan retornes un model Eloquent directament, Laravel el converteix a JSON respectant els atributs $hidden i $visible del model. Això vol dir que camps sensibles com password no es retornaran si els has marcat com a ocults.

L'objecte Response#

Per a un control més precís, pots crear una instància de Response amb el helper response(). Això et permet establir el codi d'estat HTTP, headers personalitzats i el contingut exacte:

return response('Contingut', 200)
    ->header('Content-Type', 'text/plain');

El primer paràmetre és el contingut de la resposta, el segon és el codi d'estat HTTP. Pots encadenar mètodes per afegir headers, cookies i altres opcions.

Respostes JSON#

Per a APIs i peticions AJAX, el mètode response()->json() és la manera estàndard de retornar JSON. Internament, estableix l'header Content-Type: application/json i codifica les dades amb json_encode():

return response()->json([
    'nom' => 'Joan',
    'email' => 'joan@exemple.com',
]);

Pots especificar un codi d'estat HTTP diferent com a segon paràmetre. Això és important per comunicar al client si l'operació ha estat exitosa o si hi ha hagut un error:

// Recurs creat correctament
return response()->json([
    'message' => 'Usuari creat',
    'user' => $user,
], 201);
 
// Error de validació
return response()->json([
    'error' => 'Les dades no són vàlides',
    'errors' => $errors,
], 422);
 
// Recurs no trobat
return response()->json([
    'error' => 'No trobat',
], 404);

Si necessites retornar JSON amb un callback per a peticions JSONP (habitual en integracions amb tercers), utilitza jsonp():

return response()
    ->json(['nom' => 'Joan'])
    ->withCallback($request->input('callback'));

Redirects#

Les redireccions són una de les respostes més habituals en aplicacions web. Després de processar un formulari, per exemple, normalment redirigiràs l'usuari a una altra pàgina. Laravel ofereix diversos helpers per crear redireccions de manera expressiva:

// Redirect a una URL
return redirect('/dashboard');
 
// Redirect a una ruta amb nom
return redirect()->route('users.index');
 
// Redirect a una ruta amb nom i paràmetres
return redirect()->route('users.show', ['id' => 1]);
 
// Redirect a l'acció d'un controlador
return redirect()->action([UserController::class, 'index']);
 
// Redirect a la pàgina anterior
return back();

Redirect amb dades flash#

Sovint necessitaràs enviar un missatge de confirmació o error juntament amb la redirecció. El mètode with() desa dades a la sessió flash, que estaran disponibles durant la següent petició i després s'eliminaran automàticament:

return redirect()
    ->route('users.index')
    ->with('success', 'Usuari creat correctament!');

A la vista Blade, pots accedir a les dades flash amb el helper session():

@if (session('success'))
    <div class="alert alert-success">
        {{ session('success') }}
    </div>
@endif

Pots enviar múltiples dades flash encadenant crides a with():

return redirect()
    ->route('orders.show', $order)
    ->with('status', 'Comanda confirmada')
    ->with('order_number', $order->number);

Redirect amb input#

Quan un formulari falla la validació, normalment voldràs redirigir l'usuari de tornada al formulari amb les dades que havia escrit. El mètode withInput() desa tot l'input a la sessió:

return back()
    ->withErrors($validator)
    ->withInput();

Això permet que a la vista Blade puguis recuperar els valors amb old():

<input type="text" name="name" value="{{ old('name') }}">

Redirect a dominis externs#

Per redirigir a una URL externa, utilitza redirect()->away(). A diferència de redirect(), aquest mètode no aplica cap validació d'URL ni afegeix el domini de l'aplicació:

return redirect()->away('https://laravel.com');

Vistes com a resposta#

Quan necessites retornar una vista amb un codi d'estat o headers personalitzats, pots fer servir response()->view() en lloc del helper view():

return response()
    ->view('errors.custom', ['message' => 'Quelcom ha fallat'], 500)
    ->header('X-Error-Code', 'CUSTOM_500');

Descàrregues i fitxers#

Laravel facilita servir fitxers com a descàrregues o mostrar-los directament al navegador. El mètode download() força el navegador a descarregar el fitxer, mentre que file() el mostra inline:

// Descarregar un fitxer amb un nom personalitzat
return response()->download($path, 'document.pdf');
 
// Descarregar amb headers personalitzats
return response()->download($path, 'report.csv', [
    'Content-Type' => 'text/csv',
]);
 
// Mostrar el fitxer directament al navegador (ideal per PDFs i imatges)
return response()->file($path);

Si estàs generant un fitxer temporal que ja no necessites després de la descàrrega, pots demanar a Laravel que l'esborri automàticament:

return response()->download($path)->deleteFileAfterSend();

Per a descàrregues generades en temps real (per exemple, un CSV generat dinàmicament), pots fer servir streamDownload():

return response()->streamDownload(function () {
    echo "Nom,Email\n";
    User::all()->each(function ($user) {
        echo "{$user->name},{$user->email}\n";
    });
}, 'usuaris.csv');

Headers personalitzats#

Pots afegir headers personalitzats a qualsevol resposta encadenant el mètode header(). Cada crida afegeix un header:

return response('Hola, món!')
    ->header('Content-Type', 'text/plain')
    ->header('X-Custom-Header', 'valor');

Per afegir múltiples headers d'un sol cop, utilitza withHeaders() amb un array associatiu:

return response($content)
    ->withHeaders([
        'Content-Type' => 'text/plain',
        'X-Custom-Header' => 'valor',
        'Cache-Control' => 'no-cache, no-store',
        'X-Frame-Options' => 'DENY',
    ]);

Cookies#

Les cookies a Laravel estan encriptades i signades automàticament amb la clau de l'aplicació. Això vol dir que el client no pot llegir-ne ni modificar-ne el contingut. Per afegir una cookie a la resposta:

return response('Hola')
    ->cookie('idioma', 'ca', 60); // Vàlida durant 60 minuts

Pots especificar opcions addicionals com el path, el domini, si requereix HTTPS i si és HTTP-only:

return response('Hola')
    ->cookie('idioma', 'ca', 60, '/', '.exemple.com', true, true);

Per eliminar una cookie, utilitza withoutCookie() o crea'n una amb un temps d'expiració passat:

return response('Hola')
    ->withoutCookie('idioma');

Respostes sense contingut#

Per a operacions que no necessiten retornar contingut (com un DELETE exitós), pots fer servir el codi d'estat 204:

return response()->noContent();
 
// O amb headers personalitzats
return response()->noContent(204, [
    'X-Action' => 'deleted',
]);

Això és habitual a les APIs RESTful, on una operació DELETE exitosa simplement confirma que el recurs s'ha eliminat sense retornar cap dada.