05 mappare rotte Laravel tramite Controller
Come abbiamo visto possiamo mappare una rotta, far passare i dati di questa rotta nei parametri della funzione anonima, fare un controllo sui tipi di dato e fare restituire dei risultati. Il problema di questo approccio sta nel fatto che se implementiamo diverse logiche nel routing per numerose rotte, otterremo un codice disordinato che va contro la filosofia del sistema MVC. Infatti in quest’ultimo deve essere il controller a gestire la logica delle richieste. La soluzione ottimale è creare un nuovo controller che gestisca le richieste, siano esse GET, POST, PUT, DELETE.
Andiamo ad inserire una rotta di default per la nostra home ( / )
Route::get('/', );
adesso come secondo parametro del metodo get() invece che una funzione andiamo ad inserire un controller specificandone il nome e lanciando il metodo index() tramite l’operatore chiocciola ( @ )
Route::get('/','HomeController@index');
Creare un controller
andiamo ora a creare il controller chiamato HomeController{} definendo il metodo index().
Esistono 2 modi per creare un controller in laravel:
metodo manuale
aggiungiamo dentro App\Http\Controllers il file HomeController.php e creiamo la classe HomeController{}
class HomeController { public function index() { return view('welcome'); } }
il metodo index() appena creato lancerà la vista predefinita welcome.blade.php. Se apriamo la home del sito, riceveremo l’errore di file/classe non trovate. Dobbiamo quindi inserire nel controller il namespace
namespace App\Http\Controllers; class HomeController { public function index() { return view('welcome'); } }
e aggiungere il percorso completo del controller anche nella rotta
Route::get('/','App\Http\Controllers\HomeController@index');
Ora tutto funziona, ma specificare sempre tutti i percorsi completi in ogni rotta e inserire i namespace ogni volta nei vari controlli, non è una soluzione ottimale. Laravel permette di dichiarare il namespace all’interno del provider RouteServiceProvider nella variabile protetta $namespace che di default possiamo trovare commentata o impostata a null
protected $namespace = 'App\Http\Controllers';
ora carichiamo la varibile nel middleware web poche righe più in basso
Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php'));
infine possiamo dichiarare direttamente solo il nome del controller nella rotta
Route::get('/','HomeController@index');
alternativa migliore
Da laravel 8 in su esiste un modo più veloce per risolvere il problema del namespace, prima dichiariamo la variabile $namespace a null in RouteServiceProvider
protected $namespace = null;
ora nella rotta, passiamo come secondo parametro un array
Route::get('/',[ \App\Http\Controllers\HomeController::class,'index']);
Nell’array avremo la classe come primo indice ( HomeController::class ) e il metodo da lanciare come secondo dato dell’array ( index() ). In effetti possiamo ancora migliorare specificando all’inizio del file di usare la classe HomeController, in modo da mettere poi nelle rotte la classe e il metodo nell’array senza specificare tutto il percorso
use App\Http\Controllers\HomeController; Route::get('/',[ HomeController::class,'index']);
metodo console
Dalla riga di comando, possiamo sfruttare il punto di ingresso di laravel artisan per numerose operazioni, con il comando route:list visualizziamo l’elenco delle rotte e la lista dei controller e vedremo aggiunto anche il nostro appena creato precedentemente, insieme al suo namespace.
| Domain | Method | URI | Name | Action | Middleware | +--------+--------+----------------------+------+----------------------+ | | GET|HEAD | / | | App\Http\Controllers\HomeController@index | web
a questo punto creiamo il controller con il comando make:controller, visualizziamo prima l’help per guardare le opzioni con il parametro –help.
php artisan make:controller --help
Creiamo un nuovo controller WelcomeController
php artisan make:controller WelcomeController
ecco il contenuto del controller creato da riga di comando
namespace App\Http\Controllers; use Illuminate\Http\Request; class WelcomeController extends Controller { // }
Come si vede viene aggiunto automaticamente il namespace, ci aggiunge l’accesso alla richiesta caricando la classe Request{}, infine crea la classe come estensione della classe predefinita Controller{}.
Vogliamo quindi mappare la prima rotta che avevamo dichiarato
Route::get('/{nome?}/{cognome?}/{eta?}', function($nome='',$cognome='',$eta=0) { return 'welcome '.$nome.' '.$cognome. ' '. $eta; }) ->where([ 'nome' => '[a-zA-Z]+', 'cognome' => '[a-zA-Z]+', 'eta' => '[0-9]{0,3}' ]);
utilizzando il controller WelcomeController e il metodo web() che creiamo
Route::get('/{nome?}/{cognome?}/{eta?}', [WelcomeController::class,'web'])
dobbiamo però dichiarare il controller nel files, lo aggiungiamo usando le dichiarazioni use multipli di php7 avvolgendo i controllers tra parentesi graffe e separandoli da virgola
use App\Http\Controllers\{HomeController, WelcomeController};
aggiungiamo la funzione web() nel nostro WelcomeController
class WelcomeController extends Controller
{
public function web($nome='',$cognome='',$eta=0)
{
return 'welcome ' . $nome . ' ' . $cognome . ' ' . $eta;
}
}
mappare parametri aggiuntivi
http://localhost:8000/pippo/paperino/15
pippo/paperino/15 sono segmenti della rotta, ma io posso far passare parametri GET tipo
http://localhost:8000/pippo/paperino/15&lang=en
per catturare possiamo usufruire della Request che era stata dichiarata dal terminale di default nella creazione del controller
use Illuminate\Http\Request;
a questo punto nella funzione web(), dopo i primi 3 parametri della rotta corrispondenti ai 3 segnaposti (nome, cognome, eta), possiamo aggiungere la Request con un nome a piacere, ma che chiamo $req per comodità
public function web($nome='',$cognome='',$eta=0, Request $req )
laravel a questo punto ci passerà un oggetto di tipo request con cui avremo accesso ai parametri della richiesta tramite il metodo input() fornito dall’oggetto request
$lang = $req->input('lang');
a questo punto basterà fare uno switch per gestire i casi delle opzioni lingua
public function web($nome='',$cognome='',$eta=0, Request $req ) { $lang = $req->input('lang'); switch ($lang) { case 'en': $messaggio = 'welcome ' . $nome . ' ' . $cognome . ' ' . $eta .' old'; break; case 'it': $messaggio = 'benvenuto ' . $nome . ' ' . $cognome . ' ' . $eta. ' anni'; } return $messaggio; }