Peticions HTTP

Com treballar amb l'objecte Request a Laravel: input, fitxers, headers i mètodes de la petició.

L'objecte Request#

Cada petició HTTP que arriba a la teva aplicació Laravel es converteix automàticament en un objecte Illuminate\Http\Request. Aquest objecte encapsula tota la informació de la petició: les dades del formulari, els fitxers pujats, els headers, les cookies, la URL, el mètode HTTP i molt més. Per accedir-hi, simplement injecta'l com a paràmetre al teu controlador o closure de ruta:

use Illuminate\Http\Request;
 
Route::post('/usuaris', function (Request $request) {
    $name = $request->input('name');
    $email = $request->input('email');
    // ...
});

En un controlador, funciona exactament igual. Laravel resol automàticament l'objecte Request des del contenidor de serveis i l'injecta al mètode:

class UserController extends Controller
{
    public function store(Request $request)
    {
        $name = $request->input('name');
        // ...
    }
}

Obtenir input#

El mètode input() és la manera principal d'accedir a les dades enviades per l'usuari. Funciona tant per a dades de formularis (POST) com per a query strings (GET). Accepta un segon paràmetre com a valor per defecte que es retorna si el camp no existeix:

// Valor específic
$name = $request->input('name');
 
// Amb valor per defecte si el camp no existeix
$name = $request->input('name', 'Anònim');
 
// Tot l'input com a array associatiu
$input = $request->all();

Laravel també permet accedir a l'input com si fossin propietats de l'objecte. Això fa el codi més net i llegible, tot i que internament fa el mateix que input():

$name = $request->name;
$email = $request->email;

Quan treballes amb formularis que tenen camps niuats (com arrays), pots accedir-hi amb notació de punt:

// <input name="address[city]" value="Andorra la Vella">
$city = $request->input('address.city');
 
// <input name="tags[]" value="laravel">
// <input name="tags[]" value="php">
$tags = $request->input('tags');    // ['laravel', 'php']
$first = $request->input('tags.0'); // 'laravel'

Filtrar l'input#

Quan necessites treballar només amb alguns camps, els mètodes only() i except() filtren l'input. Això és molt útil per a mass assignment o per ignorar camps com tokens CSRF o confirmacions de contrasenya:

// Només els camps especificats
$data = $request->only(['name', 'email']);
 
// Tot excepte els camps especificats
$data = $request->except(['_token', 'password_confirmation']);

Comprovar la presència de camps#

Laravel ofereix diversos mètodes per comprovar si un camp existeix o té un valor. La diferència entre ells és subtil però important:

// has(): el camp existeix a la petició (pot ser buit)
if ($request->has('name')) {
    // ...
}
 
// filled(): el camp existeix i NO és buit
if ($request->filled('name')) {
    // ...
}
 
// missing(): el camp NO existeix a la petició
if ($request->missing('name')) {
    // ...
}
 
// whenHas(): executa un callback si el camp existeix
$request->whenHas('name', function (string $input) {
    // Fer alguna cosa amb $input
});
 
// whenFilled(): executa un callback si el camp existeix i no és buit
$request->whenFilled('name', function (string $input) {
    // Fer alguna cosa amb $input
}, function () {
    // El camp no existeix o és buit
});

Pots comprovar múltiples camps alhora amb has(). El mètode retorna true només si tots els camps existeixen:

if ($request->has(['name', 'email'])) {
    // Ambdós camps existeixen
}
 
// hasAny(): retorna true si almenys un camp existeix
if ($request->hasAny(['name', 'nickname', 'alias'])) {
    // Almenys un dels tres existeix
}

Input booleà i de data#

Quan treballes amb camps de tipus checkbox o valors que representen booleans, el mètode boolean() converteix automàticament valors com "1", "true", "on" i "yes" a true:

// <input type="checkbox" name="active" value="1">
$active = $request->boolean('active'); // true o false

Per a camps de data, el mètode date() retorna una instància de Carbon, que facilita la manipulació de dates:

$birthday = $request->date('birthday');           // Carbon
$deadline = $request->date('deadline', 'd/m/Y');  // Amb format personalitzat

Input antic (Old Input)#

Quan un formulari falla la validació i necessites tornar a mostrar les dades que l'usuari havia escrit, Laravel pot desar l'input a la sessió. Això es coneix com "flashing input":

// Desar tot l'input a la sessió
$request->flash();
 
// Desar només alguns camps (mai desis contrasenyes)
$request->flashOnly(['name', 'email']);
$request->flashExcept(['password']);

La manera més habitual és combinar-ho amb una redirecció. El mètode withInput() desa automàticament l'input a la sessió:

return redirect('/formulari')
    ->withErrors($validator)
    ->withInput();

A la vista Blade, pots recuperar l'input antic amb el helper old():

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

Query strings#

Quan les dades vénen de la URL (com en una cerca o un filtre), pots accedir-hi amb el mètode query(). La diferència amb input() és que query() només llegeix els paràmetres de la URL, mentre que input() busca tant a la URL com al cos de la petició:

// GET /cerca?q=laravel&page=2
 
$query = $request->query('q');       // 'laravel'
$page = $request->query('page', 1);  // 2
 
// Tots els paràmetres de la query string
$allQuery = $request->query(); // ['q' => 'laravel', 'page' => '2']

Fitxers#

Per treballar amb fitxers pujats, el mètode file() retorna una instància de UploadedFile. Abans d'operar amb un fitxer, és recomanable comprovar que s'ha pujat correctament amb hasFile():

if ($request->hasFile('avatar')) {
    $file = $request->file('avatar');
 
    // Desar el fitxer al disc 'public' dins del directori 'avatars'
    $path = $file->store('avatars', 'public');
}

El mètode store() genera automàticament un nom de fitxer únic per evitar col·lisions. Si vols especificar el nom tu mateix, utilitza storeAs():

$path = $request->file('avatar')->storeAs(
    'avatars',
    $user->id . '.jpg',
    'public'
);

L'objecte UploadedFile proporciona mètodes per obtenir informació sobre el fitxer i validar-lo:

$file = $request->file('avatar');
 
$extension = $file->extension();               // 'jpg'
$size = $file->getSize();                      // mida en bytes
$originalName = $file->getClientOriginalName(); // nom original del client
$mimeType = $file->getMimeType();              // 'image/jpeg'
$isValid = $file->isValid();                   // si la pujada ha estat correcta

Quan el formulari permet pujar múltiples fitxers, pots accedir-hi com un array:

// <input type="file" name="photos[]" multiple>
 
$files = $request->file('photos');
 
foreach ($files as $file) {
    $path = $file->store('photos', 'public');
}

Headers i informació de la petició#

L'objecte Request dona accés a tota la informació de la petició HTTP, no només a l'input de l'usuari. Pots obtenir la URL, el mètode HTTP, la IP del client i els headers:

// URL i path
$uri = $request->path();        // 'usuaris/1'
$url = $request->url();         // 'http://app.test/usuaris/1'
$fullUrl = $request->fullUrl(); // 'http://app.test/usuaris/1?page=2'
 
// Mètode HTTP
$method = $request->method();   // 'POST'
 
// IP del client
$ip = $request->ip();           // '127.0.0.1'

Per comprovar el mètode HTTP o si la URL coincideix amb un patró:

if ($request->isMethod('post')) {
    // La petició és un POST
}
 
if ($request->is('admin/*')) {
    // La URL comença per 'admin/'
}
 
if ($request->routeIs('users.*')) {
    // La ruta amb nom comença per 'users.'
}

Per accedir als headers de la petició, utilitza el mètode header(). Si l'header no existeix, retorna null o el valor per defecte que especifiquis:

$contentType = $request->header('Content-Type');
$custom = $request->header('X-Custom-Header', 'valor per defecte');
 
// Token Bearer de l'header Authorization
$token = $request->bearerToken();

Negociació de contingut#

Laravel permet comprovar quins tipus de contingut accepta el client. Això és especialment útil per a APIs que necessiten respondre en formats diferents segons el que demani el client:

// Comprovar si el client accepta un tipus concret
if ($request->accepts(['text/html', 'application/json'])) {
    // ...
}
 
// Determinar quin tipus prefereix el client
$preferred = $request->prefers(['text/html', 'application/json']);
 
// Comprovar si el client espera JSON
if ($request->expectsJson()) {
    return response()->json(['error' => 'No trobat'], 404);
}

El mètode expectsJson() és especialment pràctic: retorna true si la petició ve amb l'header Accept: application/json o si és una petició AJAX. Laravel l'utilitza internament per decidir si retornar errors en format JSON o com una redirecció amb errors a la sessió.