LARAVEL ROUTES

In laravel le URL  vengono gestite con il meccanismo del routing, che provvede ad effettuare un collegamento tra una URL e alcune funzionalità dell’applicazione.

Con il meccanismo del routing, digitando sul browser  http://esempio.it/ordini non deve esserci necessariamente corrispondenza con una risorsa fisica presente sul server (cartella o file), ma grazie al routing l’applicazione è in grado di attivare le funzionalità associate all’ URL che possono essere gestite mediante una closure , un controller, una view o altro.

Tra i  vantaggi di una tale funzionalità vi è anche quello di ottenere delle URL parlanti, tanto apprezzate dai motori di ricerca.

Vediamo qualche esempio pratico:

Come prima cosa creiamo un’applicazione che utilizzeremo negli esempi che seguiranno.

Posizioniamoci nella DocumentRoot del nostro server e digitiamo:

composer create-project –prefer-dist laravel/laravel laraapp

Accediamo alla cartella che ospiterà l’applicazione e che porta il suo nome

cd laraapp

Supponendo di aver già editato e configurato le variabili d’ambiente presenti nel file .env, spostiamoci nella cartella routes ed editiamo il file web.php (che conterrà tutte le routes dell’applicazione dotate di sessione, mentre quelle stateless saranno inserite nel file api.php) , che apparirà così:

A questo punto creiamo la nostra prima route che corrisponderà alla seguente URL http://laraapp.webserver/esempio-prima-route (stiamo supponendo che l’indirizzo del server sia http://laraapp.webserver).

La prima funzionalità la otterremo mediante una closure  come di seguito indicato:

Route::get('/esempio-prima-route', function () {
return "Benvenuti!!";
});

Digitando sul nostro browser http://www.laraapp.webserver/esempio-prima-route, avremo come output la stringa Benvenuti!!

Le poche righe di codice vengono interpretate così:

Quando si digita nella barra degli indirizzi del browser http://laraapp.webserver/esempio-prima-route, viene eseguito il codice all’interno della function e viene restituito come output la stringa Benvenuti!!.

File web.php con esempio di route con closure

Come già accennato, tutte le routes che sono definite all’interno del file  routes/web.php costituiscono la nostra interfaccia web e sono assegnate al web middleware group (vedremo in un altro articolo di cosa si tratta) che si occupa di gestirne le sessioni e la protezione contro attacchi CSRF (cross site script forgery). Invece, le routes all’interno del file routes/api.php sono routes stateless e vengono gestite dall’ api middleware group.

Un’alternativa alle closure è quella di associare una route al metodo presente all’interno di una classe controller, vediamo come ciò sia possibile:

come prima cosa definiamo una classe controller che chiameremo primocontroller, lo faremo utilizzando la riga di comando ed in particolare i comandi del tipo php artisan.

Posizioniamoci all’interno della cartella laraapp (cartella applicazione) e digitiamo quanto segue:

php artisan make:controller primocontroller

Laravel creerà all’interno di app/Http/controllers un file di nome primocontroller.php con la definizione della classe.

Aggiungiamo all’interno della classe il metodo pubblico index come illustrato nell’immagine seguente:

A questo punto riapriamo il file routes/web.php e modifichiamolo aggiungendo la route seguente:

Route::get(‘/primocontroller’, ‘primocontroller@index’);

File web.php modificato con aggiunta route che chiama metodo controller

Questa route chiama il metodo pubblico di nome index presente nella classe primocontroller e restituisce in output, nella finestra del browser, la stringa “Chiamata verso controller riuscita!!!”.

Alle routes definite all’interno del file routes/api.php, il middleware api groups aggiungerà il prefisso api, in pratica definendo, nel file api.php, la route seguente:

Route::get('/esempioapi',function(){
return "Esempio route con via api";
});

la sua url sarà http://laraapp.webserver/api/esempioapi.

Finora abbiamo definito sempre route che utilizzano il metodo HTTP GET, ma occorre precisare che il metodo GET non è l’unico metodo utilizzabile, di seguito l’elenco degli altri metodi supportati:

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

Talvolta vi è la necessità di registrare una URL che risponda a più metodi HTTP, in questi casi vengono in aiuto le seguenti scorciatoie:

Route::match(['get', 'post'], '/', function () {
    //
});

Route::any('/miaroute', function () {
    //
});

Il metodo match prevede come primo argomento un array contenente i metodi associati alla route specificata nel secondo argomento, nel terzo argomento va specificata la action.

il metodo any associa la stessa route a tutti i metodi (GET,POST, PUT ecc.)

PROTEZIONE CSRF (cross site request forgery)

Ogni form HTML collegato ad una web route di tipo POST, PUT o DELETE deve includere il campo nascosto  CSRF Token altrimenti viene rigettato.

Di seguito un esempio di come introdurre tale campo nei form:

<form method="POST" action="/postroute">
    @csrf
    ...
</form>

Questo produrrà quanto segue:

<form method="POST" action="/postroute">
   <input type="hidden" name="_token" value="dhdhhfdhfhfhfeooeow"> 
    ...
</form>

REDIRECT

Mediante il redirect si può fare in modo di indirizzare una URL verso un’altra URL.

Se vogliamo fare in modo che l’URL http://laraapp.webserver/origine  venga rediretta verso http://laraapp.webserver/destinazione, è sufficiente definire la seguente route all’interno del file routes/web.php:

Route::redirect(‘/origine’,’/destinazione’);

Se non viene utilizzato un terzo parametro, viene restituito lo stato 302 (questo stato viene restituito quando una url è stata temporaneamente spostata verso un’altra), se invece lo spostamento è permanente, conviene passare un terzo parametro con valore pari a 301.

Route::redirect(‘/origine’,’/destinazione’,301);

Quest’ultimo è equivalente al seguente:

Route::permanentRedirect(‘/origine’,’/destinazione’);

VIEW ROUTE

Una view (vista) contiene il codice HTML di presentazione.  Laravel usa le view per separare la logica dell’applicazione, affidata ai controllers, dall’interfaccia di presentazione gestita mediante le view e con l’ausilio del blade engine, cose che approfondiremo in seguito.

In questa fase, vediamo semplicemente come una route possa essere utilizzata per richiamare una view, che magari presenti un modulo per raccogliere i dati dell’utente, mostri una pagina di benvenuto o altro.

Route::view(‘/benvenuto’,’welcome’);

Nel codice riportato sopra, notiamo la presenza di due parametri, il primo corrisponde alla route ‘/benvenuto’, il secondo è il nome della view ‘welcome’ al quale corrisponde un file welcome.blade.php all’interno della cartella resources/views (resources/views/welcome.blade.php), il percorso resources/views, essendo quello predefinito non va specificato e viene incluso automaticamente dal framework Laravel, blade indica che si sta usando blade template engine e non c’è bisogno di specificarlo come pure l’estensione .php è sottintesa, questi argomenti verranno trattati in dettaglio in un prossimo articolo.

Digitando nella barra degli indirizzi del browser l’URL http://laraapp.webserver/benvenuto, verrà inviato al browser il codice html restituito dalla view, che mostrerà una pagina di benvenuto.

Un modo equivalente per ottenere la stessa cosa è il seguente: 

Route::get(‘/benvenuto’, function () {
           return view(‘welcome’);
  });

in cui la view viene richiamata da una funzione helper all’interno della closure.

PASSAGGIO DI PARAMETRI AD UNA ROUTE

Nelle route è possibile passare parametri, per farlo bisogna racchiudere il nome del parametro, all’interno dell’URL, tra parentesi graffe:

Route::get(‘/datiutente/{id}’,function($id) {

  return “Identificativo utente: ” . $id;

});

Non si ha alcun limite al numero di parametri definibili:

Route::get(‘/articolo/{id}/commento/{idcommento}’,function($id,$idcommento) {

   return “Articolo: ” .  $id . ” Commento: ” . $idcommento ;

});

I parametri utilizzati vengono passati alle routes callback o ai controllers in base al loro ordine, il loro nome all’interno delle callback o dei controller non è vincolante, ad esempio la route precedente avrebbe potuto assumere questo aspetto:

Route::get(‘/articolo/{id}/commento/{idcommento}’,function($idutente,$idcomm) {

   return “Articolo: ” .  $idutente . ” Commento: ” . $idcomm ;

});

Un parametro può essere opzionale, per renderlo tale è necessario far seguire il suo nome da un ?.

In questo caso occorre ricordarsi di assegnargli nella callback o nel controller che gestisce la route un valore di default:

Route::get('utente/{nome?}', function ($nome = null) {
    return $nome;
});

Route::get('utente/{nome?}', function ($nome = 'Francesco') {
    return $nome;
});

Se si vuole vincolare il formato  di un parametro, si deve usare il metodo where come si evince dagli esempi seguenti:

Route::get('utente/{nome}', function ($nome) {
return $nome;
})->where('nome','[A-Za-z]');

L’espressione regolare ‘[A-Za-z]’ vincola il parametro nome a contenere solo caratteri alfabetici.

Route::get('utente/{id}', function ($id) {
    //
})->where('id', '[0-9]+');

 

In questo caso il parametro id accetta solo caratteri numerici.

Se si vuole vincolare un parametro globalmente, in tutte le route, senza dover specificare ogni volta il suo formato, è sufficiente editare il file app/Providers/RouteServiceProvider.php ed all’interno del suo metodo boot digitare quanto segue:

public function boot()
{
    Route::pattern('id', '[0-9]+');

    parent::boot();
}

Una volta che si è inserita la riga Route::pattern(‘id’,'[0-9]’); in ogni route in cui verrà usato il parametro con nome id,  esso potrà assumere solo valori numerici, altrimenti verrà restituita un’eccezione.

Assegnare un nome ad una route

Se nell’applicazione è necessario utilizzare l’URL associata ad una route più volte; per generare più facilmente l’URL è comodo assegnare un mome alla route mediante il metodo name.

Esempio 1 con funzione di callback

Route::
get('utente/profilo', function () { // })->name('profilo_utente');
Esempio 2 con richiamo metodo controller

Route::
get('utente/profilo', 'UtenteProfiloController@show')->name('profilo_utente')
;

Una volta che avete assegnato un nome ad una route, laddove sarà necessario rigenerarla, per utilizzarla come action di un form o come attributo href di un link o come url a cui fare un redirect o per altri motivi, basterà usare la sintassi seguente:

// Generazione URL mediante la funzione helper route ed assegnazione ad una variabile
$url = route('profilo_utente');

// Generazione Redirect...
return redirect()->route('profilo_utente');

Se le routes alle quali è stato assegnato un nome contengono parametri, è possibile passarli alla funzione di callback o al controller così:

Route::get('utente/{id}/profilo', function ($id) {
    //
})->name('profilo_utente');

$url = route('profilo_utente', ['id' => 1]);

Se si vuole ispezionare se la richiesta corrente proviene da una route con un determinato nome, lo si può fare utilizzando il metodo named

 if ($request->route()->named('profilo_utente')) {
        //
    }

RAGGRUPPARE LE ROUTES

Se alcune routes condividono attributi comuni, allora può essere molto utile raggrupparle e riunirle in un gruppo.

Ciò che più routes possono condividere può consistere in uno o più  middleware (meccanismo che consente di filtrare una richiesta per verificarne alcuni aspetti, tra questi per esempio il processo di autenticazione…approfondiremo i middleware in altri articoli), namespaces (spazio dei nomi, una caratteristica che permette di unificare classi e costanti sotto un unico nome), prefissi, appartenenza a sotto-domini ecc.

Ecco alcuni esempi:

Route::middleware(['middleware1', 'middleware1'])->group(function () {
    
Route::get('/', function () {
// Usa middleware1 & Middleware2

}); Route::get('utente/profilo', function () {
// Usa middleware1 & Middleware2
});
});

Nell’esempio sopra ciò che le routes devono condividere sono i due middleware (middleware1 e middleware2) che vengono elencati in un array, segue la chiamata al metodo group, che all’interno della function elenca tutte le routes del gruppo.

Route::namespace('Admin')->group(function () {
    
// Qui vanno elencate tutte le routes che condividono il Namespace "App\Http\Controllers\Admin"

}
)
;

Nell’esempio sopra al Namespace predefinito App\Http\Controllers\ viene aggiunto Admin, quindi il namespace completo delle routes elencate sarà App\Http\Controllers\Admin

Route::prefix('admin')->group(function () {
    
Route::get('utenti', function () {
// la route sarà "/admin/utenti"

});
});

Nell’esempio sopra viene mostrato come procedere quando più routes condividono lo stesso prefisso.

Route::name('admin.')->group(function () {
    Route::get('users', function () {
        // Questa Route avrà come nome "admin.utenti"...
    })->name('utenti');
    
Route::get('articoli',function(){

// Questa Route avrà come nome "admin.articoli"...
})->name('articoli');
}
);

L’esempio sopra esempio mostra come sia possibile raggruppare più routes che nel nome assegnato debbano condividere il prefisso admin.

Esempi di routes raggruppate

Fallback Routes

Il metodo fallback ci permette di decidere cosa restituire all’utente quando nessuna route definita soddisfa la richiesta.

Generalmente quando una request non trova riscontro in una route viene restituita una pagina 404, volendo, però, attraverso il metodo fallback questo comportamento può essere personalizzato.

Inserendo nel file routes/web.php il codice seguente:

Se si digita nella barra degli indirizzi del browser una url a cui non corrisponde alcuna route (es. http://laraapp.webserver/nonesisto ) verrà visualizzato il messaggio “Url non trovata”.

Limitare il numero di accessi nell’unità di tempo

Utilizzando il middleware throttle, incluso in Laravel, si ha la possibilità di limitare il massimo numero di accessi ad una o ad un gruppo di routes in un arco temporale.

Di seguito un esempio di codice:

Il codice sopra limita al gruppo di routes di superare più di 5 accessi al minuto.

Se si supera il massimo numero di accessi consentito si ottiene una risposta simile alla seguente:

METODI per i Moduli (FORM)

Come è noto a chi ha già esperienza di sviluppo web, i form html supportano solo i metodi GET e POST, ma se vi è la necessita di usare gli altri metodi che il protocollo http mette a disposizione (PUP,PATCH,DELETE), ecco come farlo facilmente utilizzando Laravel, aggiungendo il campo _method dandogli come valore il nome del metodo (PUT,DELETE,PATCH):

<form action=”/azione”>

  <input type=”hidden” name=”_method”  value=”put”>

  <input type=”hidden” name=”_token” value=”yrry848485uurur”>

 …altri campi

</form>

Se si sta utilizzando il blade template engine, allora è possibile la semplificazione seguente:

<form action="/azione">
@method('PUT')

@csrf
...altri campi
</form>

Accedere alla route corrente

Chiudiamo questo lungo articolo presentando alcuni utili metodi offerti dalla route facade che restituiscono la route corrente, il nome associato e l’azione associata ad un eventuale form presente nella pagina.

$route = Route::current();

$name = Route::currentRouteName();

$action = Route::currentRouteAction();

3 Comments to “LARAVEL ROUTES”

  1. Grazie per questi articoli, materiale molto prezioso, è raro trovare guide in italiano spiegate così bene.

    1. Grazie mille. Dovrei fare qualche aggiornamento a queste guide perché è passato un po’ di tempo e molte cose in Laravel con la versione 8 sono cambiate, ci sono molte novità che andrebbero integrate nelle guide.

      1. Sì, è vero è cambiato molto rispetto a quanto riportato qui. Attualmente Laravel è arrivato alla versione 9, purtroppo gli impegni attuali mi impediscono di fare aggiornamenti.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *