Prologo
Primi Passi
Architettura
Le Basi
Approfondimenti
Package
Risposte
Creare Risposte
Stringhe e Array
Tutte le route e i controller dovrebbero restituire una risposta da inviare al browser dell’utente. Laravel offre diversi modi per restituire risposte. La risposta più semplice è restituire una stringa da una route o un controller. Il framework convertirà automaticamente la stringa in una risposta HTTP completa:
Route::get('/', function () {
return 'Hello World';
});
Oltre a restituire stringhe dalle tue route e controller, puoi anche restituire array. Il framework convertirà automaticamente l’array in una risposta JSON:
Route::get('/', function () {
return [1, 2, 3];
});
Sapevi che puoi anche restituire Eloquent collection dalle tue route o controller? Verranno automaticamente convertite in JSON. Prova!
Oggetti di Risposta
Di solito, non restituirai semplici stringhe o array dalle azioni delle tue route. Invece, restituirai istanze di Illuminate\Http\Response
o view.
Restituire un’istanza completa di Response
ti permette di personalizzare il codice di stato HTTP e gli header della risposta. Un’istanza di Response
eredita dalla classe Symfony\Component\HttpFoundation\Response
, che offre vari metodi per creare risposte HTTP:
Route::get('/home', function () {
return response('Hello World', 200)
->header('Content-Type', 'text/plain');
});
Modelli Eloquent e Collezioni
Puoi anche restituire direttamente i modelli e le collezioni dell’Eloquent ORM dalle tue rotte e controller. Quando lo fai, Laravel convertirà automaticamente i modelli e le collezioni in risposte JSON rispettando gli attributi nascosti del modello:
use App\Models\User;
Route::get('/user/{user}', function (User $user) {
return $user;
})
Aggiungere Header alle Risposte
Tieni presente che la maggior parte dei metodi response sono concatenabili, permettendo una costruzione "fluente" delle istanze di risposta. Ad esempio, puoi usare il metodo header
per aggiungere una serie di headers alla risposta prima di inviarla all’utente:
return response($content)
->header('Content-Type', $type)
->header('X-Header-One', 'Header Value')
->header('X-Header-Two', 'Header Value');
Oppure, puoi usare il metodo withHeaders
per specificare un array di header da aggiungere alla risposta:
return response($content)
->withHeaders([
'Content-Type' => $type,
'X-Header-One' => 'Header Value',
'X-Header-Two' => 'Header Value',
]);
Middleware per il Controllo della Cache
Laravel include un middleware cache.headers
, che può essere utilizzato per impostare rapidamente l’intestazione Cache-Control
per un gruppo di route. Le direttive devono essere fornite usando l’equivalente in "snake case" della direttiva cache-control corrispondente e devono essere separate da un punto e virgola. Se etag
è specificato nell’elenco delle direttive, un hash MD5 del contenuto della risposta verrà automaticamente impostato come identificatore ETag:
Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {
Route::get('/privacy', function () {
// ...
});
Route::get('/terms', function () {
// ...
});
});
Allegare Cookie alle Risposte
Puoi allegare un cookie a un’istanza Illuminate\Http\Response
uscente usando il metodo cookie
. Devi passare il nome, il valore e il numero di minuti per cui il cookie deve essere considerato valido a questo metodo:
return response('Hello World')->cookie(
'name', 'value', $minutes
);
Il metodo cookie
accetta anche altri argomenti che vengono usati meno frequentemente. Generalmente, questi argomenti hanno lo stesso scopo e sintassi degli argomenti che verrebbero dati al metodo nativo di PHP setcookie:
return response('Hello World')->cookie(
'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
);
Se vuoi assicurarti che un cookie venga inviato con la risposta in uscita ma non hai ancora un’istanza di quella risposta, puoi usare la facciata Cookie
per "mettere in coda" i cookie per essere allegati alla risposta quando viene inviata. Il metodo queue
accetta gli argomenti necessari per creare un’istanza di cookie. Questi cookie saranno allegati alla risposta in uscita prima che venga inviata al browser:
use Illuminate\Support\Facades\Cookie;
Cookie::queue('name', 'value', $minutes);
Generazione di istanze di Cookie
Se desideri creare un’istanza di Symfony\Component\HttpFoundation\Cookie
che può essere allegata a una istanza di response in un secondo momento, puoi usare l’helper globale cookie
. Questo cookie non verrà inviato al client a meno che non sia allegato a una istanza di response:
$cookie = cookie('name', 'value', $minutes);
return response('Hello World')->cookie($cookie);
Scadenza anticipata dei cookie
Puoi rimuovere un cookie facendolo scadere tramite il metodo withoutCookie
di una risposta in uscita:
return response('Hello World')->withoutCookie('name');
Se non hai ancora un’istanza della risposta in uscita, puoi usare il metodo expire
della facade Cookie
per scadere un cookie:
Cookie::expire('name');
Cookies e Crittografia
Di default, grazie al middleware Illuminate\Cookie\Middleware\EncryptCookies
, tutti i cookie generati da Laravel sono criptati e firmati in modo che non possano essere modificati o letti dal client. Se desideri disabilitare la crittografia per un sottoinsieme di cookie generati dalla tua applicazione, puoi utilizzare il metodo encryptCookies
nel file bootstrap/app.php
della tua applicazione:
->withMiddleware(function (Middleware $middleware) {
$middleware->encryptCookies(except: [
'cookie_name',
]);
})
Reindirizzamenti
Le risposte di reindirizzamento sono istanze della classe Illuminate\Http\RedirectResponse
e contengono gli header necessari per reindirizzare l’utente a un altro URL. Ci sono diversi modi per generare un’istanza di RedirectResponse
. Il metodo più semplice è utilizzare l’helper globale redirect
:
Route::get('/dashboard', function () {
return redirect('/home/dashboard');
});
A volte potresti voler reindirizzare l’utente alla sua posizione precedente, ad esempio quando un modulo inviato non è valido. Puoi farlo usando la funzione helper globale back
. Poiché questa funzionalità utilizza la sessione, assicurati che la route che chiama la funzione back
stia utilizzando il gruppo middleware web
:
Route::post('/user/profile', function () {
// Validate the request...
return back()->withInput();
});
Reindirizzamento a Rotte Nominate
Quando chiami l’helper redirect
senza parametri, viene restituita un’istanza di Illuminate\Routing\Redirector
, permettendoti di chiamare qualsiasi metodo sull’istanza Redirector
. Ad esempio, per generare una RedirectResponse
verso una rotta nominata, puoi usare il metodo route
:
return redirect()->route('login');
Se la tua rotta ha parametri, puoi passarli come secondo argomento al metodo route
:
// Per una rotta con il seguente URI: /profile/{id}
return redirect()->route('profile', ['id' => 1]);
Popolare i Parametri con i Modelli Eloquent
Se stai reindirizzando a una route con un parametro "ID" che viene preso da un modello Eloquent, puoi passare direttamente il modello. L’ID verrà estratto automaticamente:
// Per una route con il seguente URI: /profile/{id}
return redirect()->route('profile', [$user]);
Se vuoi personalizzare il valore che viene inserito nel parametro della route, puoi specificare la colonna nella definizione del parametro (/profile/{id:slug}
) oppure puoi sovrascrivere il metodo getRouteKey
nel tuo modello Eloquent:
/**
* Ottieni il valore della chiave di route del modello.
*/
public function getRouteKey(): mixed
{
return $this->slug;
}
Reindirizzare alle Azioni del Controller
Puoi anche generare reindirizzamenti alle azioni del controller. Per farlo, passa il controller e il nome dell’azione al metodo action
:
use App\Http\Controllers\UserController;
return redirect()->action([UserController::class, 'index']);
Se la route del tuo controller richiede parametri, puoi passarli come secondo argomento al metodo action
:
return redirect()->action(
[UserController::class, 'profile'], ['id' => 1]
);
Reindirizzare a Domini Esterni
A volte potresti dover reindirizzare a un dominio esterno alla tua applicazione. Puoi farlo chiamando il metodo away
, che crea una RedirectResponse
senza ulteriori codifiche URL, validazioni o verifiche:
return redirect()->away('https://www.google.com');
Reindirizzamento Con Dati Flash della Sessione
Reindirizzare a un nuovo URL e flashare dati nella sessione di solito avviene contemporaneamente. Di solito, questo avviene dopo aver eseguito con successo un’azione quando flashi un messaggio nella sessione. Per comodità, puoi creare un’istanza RedirectResponse
e flashare i dati nella sessione in una singola catena di metodi:
Route::post('/user/profile', function () {
// ...
return redirect('/dashboard')->with('status', 'Profile updated!');
});
Dopo che l’utente è stato reindirizzato, puoi visualizzare il messaggio flashato dalla sessione. Ad esempio, usando la sintassi Blade:
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
Reindirizzare con Input
Puoi usare il metodo withInput
fornito dall’istanza RedirectResponse
per salvare i dati di input della richiesta corrente nella sessione prima di reindirizzare l’utente a una nuova destinazione. Questo di solito si fa se l’utente ha riscontrato un errore di validazione. Una volta salvati gli input nella sessione, puoi facilmente recuperarli nella successiva richiesta per ripopolare il modulo:
return back()->withInput();
Altri Tipi di Response
La funzione helper response
può essere utilizzata per generare altri tipi di istanze di response. Quando il helper response
viene chiamato senza argomenti, viene restituita un’implementazione del contratto Illuminate\Contracts\Routing\ResponseFactory
. Questo contratto fornisce diversi metodi utili per generare le response.
Risposte con View
Se hai bisogno di controllare lo status e gli header della response ma anche di ritornare una view come contenuto della response, usa il metodo view
:
return response()
->view('hello', $data, 200)
->header('Content-Type', $type);
Naturalmente, se non hai bisogno di passare un codice di status HTTP personalizzato o header personalizzati, puoi usare la funzione helper globale view
.
Risposte JSON
Il metodo json
imposta automaticamente l’header Content-Type
su application/json
, oltre a convertire l’array fornito in JSON utilizzando la funzione PHP json_encode
:
return response()->json([
'name' => 'Abigail',
'state' => 'CA',
]);
Se desideri creare una risposta JSONP, puoi utilizzare il metodo json
in combinazione con il metodo withCallback
:
return response()
->json(['name' => 'Abigail', 'state' => 'CA'])
->withCallback($request->input('callback'));
Download dei File
Il metodo download
può essere usato per generare una risposta che forza il browser dell’utente a scaricare il file al percorso specificato. Il metodo download
accetta un filename come secondo argomento, che determinerà il nome del file che l’utente vedrà durante il download. Infine, puoi passare un array di HTTP headers come terzo argomento del metodo:
return response()->download($pathToFile);
return response()->download($pathToFile, $name, $headers);
Symfony HttpFoundation, che gestisce i download dei file, richiede che il file da scaricare abbia un filename ASCII.
Risposte con File
Il metodo file
può essere utilizzato per mostrare un file, come un’immagine o un PDF, direttamente nel browser dell’utente anziché avviare un download. Questo metodo accetta il percorso assoluto del file come primo argomento e un array di header come secondo argomento:
return response()->file($pathToFile);
return response()->file($pathToFile, $headers);
Risposte in Streaming
Trasmettendo i dati al client man mano che vengono generati, puoi ridurre significativamente l’uso della memoria e migliorare le prestazioni, soprattutto per risposte molto grandi. Le risposte in streaming permettono al client di iniziare a elaborare i dati prima che il server abbia finito di inviarli:
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); // Simula un ritardo tra i pezzi...
}
}, 200, ['X-Accel-Buffering' => 'no']);
});
Internamente, Laravel utilizza la funzionalità di buffering dell’output di PHP. Come puoi vedere nell’esempio sopra, dovresti usare le funzioni
ob_flush
eflush
per inviare il contenuto bufferizzato al client.
Risposte JSON in Streaming
Se hai bisogno di trasmettere dati JSON progressivamente, puoi utilizzare il metodo streamJson
. Questo metodo è particolarmente utile per grandi set di dati che devono essere inviati gradualmente al browser in un formato facilmente parsabile da JavaScript:
use App\Models\User;
Route::get('/users.json', function () {
return response()->streamJson([
'users' => User::cursor(),
]);
});
Download in Streaming
A volte potresti voler trasformare la risposta stringa di un’operazione in una risposta scaricabile senza dover scrivere i contenuti dell’operazione su disco. In questo caso puoi usare il metodo streamDownload
. Questo metodo accetta una callback, un nome di file e un array opzionale di headers come argomenti:
use App\Services\GitHub;
return response()->streamDownload(function () {
echo GitHub::api('repo')
->contents()
->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme.md');
Macro delle Risposte
Se desideri definire una risposta personalizzata che puoi riutilizzare in diverse tue rotte e controller, puoi utilizzare il metodo macro
sulla facade Response
. Di solito, dovresti chiamare questo metodo dal metodo boot
di uno dei service providers della tua applicazione, come il service provider App\Providers\AppServiceProvider
:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Response::macro('caps', function (string $value) {
return Response::make(strtoupper($value));
});
}
}
La funzione macro
accetta un nome come primo argomento e una closure come secondo argomento. La closure della macro verrà eseguita quando si chiama il nome della macro da un’implementazione di ResponseFactory
o dall’helper response
:
return response()->caps('foo');