Nel capitolo precedente abbiamo accennato al fatto che nella directory routes
possiamo (e dobbiamo) definire le routes del nostro progetto e che esse svolgono il fondamentare ruolo di gestire le richieste via URL (quindi richieste HTTP) del nostro progetto. È bene specificare che Laravel non gestisce nessuna riscrittura degli URL (url rewriting), ma semplicemente intercetta tutte le richieste HTTP e le indirizza alla pagina public/index.php
, che a sua volta avvia il framework e controlla se c’è qualche route specificata per l’URL richiesto.
In altre parole, chiamando https://miodominio.com/user/1
, la richiesta viene gestita se nei file routes/web.php
c’è una route definita per accogliere la richiesta verso /user/1
e rispondere di conseguenza. La risposta può essere, naturalmente una risposta in JSON (nel caso di una API), o una “normale” pagina web con CSS e JS annessi, magari utilizzando il template engine Blade.
Partiamo quindi dal caso più semplice, rispondiamo all’url /benvenuto
con un con messaggio estremamente simpatico:
// routes/web.php // ... // aggiungiamo questa route in coda Route::get('/benvenuto', function () { return 'Benvenut* in Laravel!'; });
Dato che in questo esempio non merita spiegazioni, passiamo ad un esempio leggermente più complesso, quello che abbiamo già utilizzato in precedenza:
Route::get('/user/{id}', function ($id) { return "Hai chiesto l'ID utente ".$id; });
Abbiamo ottenuto l’ID utente da un segmento dell’URL. Possiamo farlo naturalmente con diversi segmenti:
Route::get('/articoli/{categoria}/prodotto/{id}', function ($categoria, $prodotto_id) { // $categoria e $prodotto_id assumeranno i valori dei segmenti corrispondenti });
E se alcuni parametri fossero opzionali? Possiamo dire a Laravel che uno o più segmenti sono opzionali utilizzando il punto interrogativo ?
in questo modo:
Route::get('/articoli/{categoria?}', function ($categoria = null) { // });
Funzionerà così sia l’URL /articoli/
che /articoli/ferramenta
, ma nel primo caso, essendo assente il parametro, otterremo il valore di default di $categoria
, cioè null
.
Possiamo vincolare il formato che i nostri parametri possono assumere utilizzando le espressioni regolari. Ad esempio, ci aspettiamo che l’ID di una news sia sempre un numero, e non una stringa. Potremmo quindi fare il routing dell’URL /news/1
in questo modo:
Route::get('/news/{id}', function ($categoria = null) { // })->where('id', '[0-9]+');
Abbiamo invocato il metodo where()
che accetta come parametri il nome del segmento e l’espressione regolare. In questo caso abbiamo utilizzato [0-9]+, ma se ad esempio ci aspettassimo una stringa (come nel caso del routing /articoli/ferramenta utilizzato in precedenza), dovremmo usare l’espressione regolare [A-Za-Z]+:
Route::get('/articoli/{categoria}', function ($categoria) { // })->where('id', '[A-Za-Z]+');
Se i parametri, fossero due (o più), dovremmo passare un’array al metodo where()
, in questo modo:
Route::get('/news/{id}/{titolo}', function ($id, $titolo) { // })->where(['id' => '[0-9]+', 'name' => '[A-Za-z]+']);
Cosa succede se questa route non “prende” l’URL interessato, perché ad esempio chiamiamo l’URL /news/sport/formula1
e non /news/99/formula1
? Semplicemente questa ruote non funzionerà, dovremmo crearne una adatta a gestire le richieste “sbagliate” ed i typo.
Vediamo poi come dare un nome alle route, perché questo nome ci potrà servire in seguito per identificarla velocemente.
Route::get('/news/formula1', function () { // })->name('formula1_news');
I gruppi di route sono utili quando una serie di route hanno un prefisso comune e si potranno quindi raggruppare molto semplicemente, in questo modo:
Route::prefix('news')->group(function () { Route::get('/formula1', function () { // URL /news/formula1 }); Route::get('/motoGP', function () { // URL /news/motoGP }); });
Naturalmente, tutti i metodi HTTP sono contemplati, quindi tutti gli esempi che abbiamo visto funzioneranno con GET
(come appunto negli esempi), ma anche con POST
, PUT
, DELETE
, PATCH
e OPTIONS
. Eccoli elencati:
Route::get(..); Route::post(..); Route::put(..); Route::patch(..); Route::delete(..); Route::options(..);
E se avessimo bisogno di fare il match per più di un metodo HTTP? Ad esempio rispondere alle richieste sia POST
che GET
verso l’indirizzo /supermega
? Possiamo farlo utilizzando il metodo match()
, passandogli un array con i metodi:
Route::match(['get', 'post'], '/supermega', function () { // });
Vediamo come gestire le routes che portano verso Model mancanti o inesistenti, come ad esempio richiedere un’articolo che non esiste nel database. Nel nostro esempio, porteremo l’utente alla route alla quale abbiamo assegnato il nome “non_trovata”.
use App\Http\Controllers\ArticoloController; use Illuminate\Http\Request; use Illuminate\Support\Facades\Redirect; Route::get('/articolo/{articolo}', [ArticoloController::class, 'show'])->missing(function (Request $request) { return redirect()->route('non_trovata'); });
Vediamo, infine, come aggiungere una route di Fallback “acchiappatutto”, che intercetti tutte le richieste che non sono state matchate dalle altre route. Di solito è quella che mostra la pagina di 404. Attenzione: dobbiamo sempre scriverla per ultima, altrimenti bloccherà le altre route!
Route::fallback(function () { // });
Una volta che abbiamo compreso e preso familiarità con le route di Laravel, possiamo passare a quello che ritengo il “Capitolo 2 delle routes”, ovvero quello che riguarda il Model binding, per sfruttare davvero a fondo le capacità di questo framework e snellire non di poco il nostro lavoro. Prosegui verso Routing e model binding con Laravel.