Salta al contenuto principale

Il Routing di Laravel: Come gestire le rotte dinamiche per una Multi-Page Applications (MPA)

Profile picture for user luca77king

Oggi parleremo del routing di Laravel, un componente del framework che ci permette di creare delle applicazioni multipage. Come funziona il routing di Laravel? Ogni volta che immettiamo un URL nella barra degli indirizzi (GET) o inviamo un modulo elettronico (POST), il routing del software gestisce queste richieste, smistandole all'interno del del framework in modo che possano essere processate.

Andiamo a vedere più da vicino questo componente. L'area di lavoro che c’interessa è all'interno della cartella routes. Qui troviamo una serie di files, uno riguarda le API che per il momento non ci interessano e poi abbiamo le rotte web. Apriamo il file web.php per vedere com'è strutturato. 

Route::get('/', function () {
   return view('welcome');
});

Come possiamo vedere abbiamo la classe Route che al momento gestisce una GET. Sarebbe più corretto usare il termine Facade, ma questo concetto lo introdurremo più avanti per non complicarci le idee. Per il momento continuiamo ad usare la parola Classe. La classe Route gestisce tutto il componente routing, con funzionalità del tipo:

  • GET, POST e PUT
  • Gestione di gruppi di rotte
  • Gestione dei sottodomini

Al momento noi abbiamo una sola rotta, la home. Possiamo capirlo perché nel primo parametro del metodo get c'è solamente uno slash. Il secondo parametro riguarda invece l’action da eseguire una volta che viene invocata la risorsa definita nel parametro precedente. In questo caso abbiamo una semplice callback che ritorna la view (vista) welcome.

La vista welcome viene creata nel processo d’installazione di Laravel. La troviamo all'interno della cartella resources/views. Più avanti la cancelleremo, ma oggi la useremo per fare un po' di pratica con il routing. Portiamoci nel percorso appena descritto e apriamo il file welcome.blade.php

Al suo interno ci sono una serie di link che puntano a risorse esterne

<div class="links">
    <a href="https://laravel.com/docs">Docs</a>
    <a href="https://laracasts.com">Laracasts</a>
    <a href="https://laravel-news.com">News</a>
    <a href="https://blog.laravel.com">Blog</a>
    <a href="https://nova.laravel.com">Nova</a>
    <a href="https://forge.laravel.com">Forge</a>
    <a href="https://vapor.laravel.com">Vapor</a>
    <a href="https://github.com/laravel/laravel">GitHub</a>
</div>

L’esercizio che faremo sarà sostituire questi link statici con rotte definite nel nostro file routes/web.php. Ritorniamo all'interno di quest’ultimo e andiamo a definire due nuove rotte all’interno dello stesso gruppo.

Route::group(['prefix' => '/test', 'as' => 'test.'], function () {
    Route::get('/index', function () {
        return 'index';
    })->name('index');
    Route::get('/show', function () {
        return 'show';
    })->name('show');
});

Vediamo cosa abbiamo scritto. Attraverso il metodo group della Classe Route abbiamo racchiuso due rotte con degli elementi in comune. Questi elementi sono riscontrabili nel primo parametro del metodo group. Si tratta di un array con due elementi, prefix e as. La prima chiave, prefix, fa riferimento al path immesso nella barra degli indirizzi, per cui ogni volta che vi sarà una richiesta HTTP con questo pattern dominio.tld/test/ risponderanno le rotte contenute all’interno di questo blocco. La seconda chiave, as, è l’alias del gruppo che dovremo rispettare le momento in cui vogliamo richiamare nel software le rotte contenute nel dato blocco.

Esaminiamo l’interno del blocco. Come possiamo vedere abbiamo duplicato l’esempio originario, cambiando il return e aggiungendo una funzionalità, name, che denomina le singole rotte. Per cui, ricordandoci quello che ho descritto nel paragrafo precedente, le due rotte avranno le seguente denominazioni

  • test.index
  • test.show

Mentre dovranno essere invocate dall’esterno con i seguenti url

  • dominio.tld/test/index
  • dominio.tld/test/show

Perfetto, ora lanciamo il comando artisan per aggiornare la cache del routing

php artisan route:clear

Torniamo all’interno del file resources/views/welcome.blade.php e andiamo a sostituire un paio di links statici con le nostre nuove rotte. La sintassi da utilizzare nelle viste, quando si utilizzano variabili è la seguente

{!! codice php !!}

In questo caso dobbiamo usare l’helper di laravel route, passandogli un solo parametro: il nome completo delle rotte, in questo modo:

<div class="links">
    <a href="/admin/post/edit/{!! route('test.index') !!}">Test Index</a>
    <a href="/admin/post/edit/{!! route('test.show') !!}">Test Show</a>
</div>

Se clicchiamo su questi link, vedremo che risponderanno le callback che abbiamo definito nel file routes/web.php

Impostare l'action di una rotta con un metodo di un Controller

Andiamo avanti, io voglio definire un controller che gestisce la risposta di queste rotte. Per fare questo, prima di tutto creo il controller attraverso artisan

php artisan make:controller TestController

Una volta lanciato il comando, troveremo un nuovo file all’interno della cartella app/Http/Controllers. Apriamo il file TestController  e andiamo a definire due metodi

public function index()
{
    return 'Sono il metodo Index del Controller Test';
}

public function show()
{
    return 'Sono il metodo Show del Controller Test';
}

Ora, torniamo sul file routes/web.php e cancelliamo la callback delle rotte create in precedenza e deleghiamo la risposta ai metodi del controller che abbiamo appena definito.

Route::group(['prefix' => '/test', 'as' => 'test.'], function () {
    Route::get('/index', 'TestController@index')->name('index');
    Route::get('/show', 'TestController@show')->name('show');
});

Ricordiamoci di aggiornare la cache del routing e se andiamo ad invocare le nostre rotte di test, vedremo a video quello che abbiamo scritto nei metodi di TestController.

Passare un parametro alla rotta

Fin qui non credo che ci siano particolari problemi, ma adesso le cose si complicano leggermente. Supponiamo che la rotta test.show abbia bisogno di un parametro, per mostrare un record specifico di un’ipotetica tabella. In soldoni, se invochiamo test/show/2 dobbiamo essere in grado di mostrare il dettaglio del record con id 2 della nostra tabella ipotetica.

Perfetto, questo è il problema da risolvere. Come procediamo? Il primo step è modificare la rotta, perché attualmente la risorsa test/show/{id} darebbe errore 404. Questo ha senso...Si tratta di una risorsa diversa rispetto a test/show.

Per cui modifichiamo l’URI della rotta test.show in questo modo 

Route::get('/show/{id}', 'TestController@show')→name('show');

Aggiorniamo la cache e da questo momento la risorsa esiste, ma non è ancora gestita. Infatti se provassimo a visitare la risorsa test/show/2 (o qualsiasi altro intero), il software ci restituirebbe un errore. Questo perché il parametro non è gestito dal Controller. L’implementazione è molto semplice, ci basterà modificare la firma del metodo show della classe TestController in questo modo

public function show($id)

A questo punto il parametro definito nella barra degli indirizzi viene gestito dal routing e passato al metodo del Controller, dove poi possiamo usarlo per lo scopo che ci eravamo prefissi.

Rendere un parametro opzionale

Potrebbe capitare la situazione in cui questo parametro non deve essere definito obbligatoriamente. Dobbiamo quindi essere in grado di renderlo opzionale. Niente di complicato, apriamo il file routes/web.php e aggiungiamo un ? all'interno delle parentesi graffe che racchiudono il parametro

Route::get('/show/{id?}', 'TestController@show')→name('show');

Aggiorniamo la cache, apriamo di nuovo la classe TestController e modifichiamo la firma del metodo show

public function show($id = null)

Finito, da questo momento saranno disponibili sia la rotta  test/show/{id} e sia la rotta  test/show