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.