Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

I controller e la gestione delle richieste in Laravel

Andiamo al cuore della logica della nostra applicazione basata su Laravel. I controller si occupano di gestire le richieste formulate dall'utente tramite il client e di rispondere in modo appropriato fornendo le risorse necessarie.
Andiamo al cuore della logica della nostra applicazione basata su Laravel. I controller si occupano di gestire le richieste formulate dall'utente tramite il client e di rispondere in modo appropriato fornendo le risorse necessarie.
Link copiato negli appunti

Associare una rotta ad un controller

Nonostante Laravel permetta di definire alcuni comportamenti direttamente nel file routes.php, questo approccio non è scalabile. La soluzione perfetta per gestire i vari entry point delle nostre applicazioni è invece l'utilizzo dei controller.

Laravel ha previsto per questa tipologia di componente una cartella dedicata: app/Http/Controllers e una classe da estendere Illuminate\Routing\Controller.

Un controller è una semplice classe che presenta diversi metodi pubblici. Ciascuno di questi ultimi viene associato ad una URL e ad un metodo HTTP. Per associare una URL ad un determinato controller si usa la sintassi NomeController@nomeMetodo. Per esempio:

//routes.php
Route::get('/users', 'UserController@getList');
//UserController.php
class UserController extends BaseController {
    public function getList() {
        return 'User1, User2, User3';
    }
}

In questo caso abbiamo associato la URL /users al metodo getList dello UserController. Come per le rotte tradizionali, anche quando utilizziamo un controller è possibile dare ad esso un nome specifico:

Route::get('/users', [ 'uses' => 'UserController@getList', 'as' => 'userList' ]);

Eventuali parametri presenti nelle rotte verranno tradotti in parametri del metodo del controller invocato.

I controller RESTful

In caso di creazione di API restful, è possibile mappare automaticamente i metodi di una classe con le URL. Grazie al metodo resource, Laravel definirà al nostro posto tutte le rotte disponibili:

Route::resource('photo', 'PhotoController');

Le URL verranno create secondo questa tabella:

Figura 1. Creazione delle URL.
Creazione delle URL

Tramite il comando da console php artisan make:controller PhotoController è possibile creare uno scheletro di controller con i metodi già definiti.

Controller impliciti

Un'ulteriore funzionalità interessante è quella offerta dal metodo controller. In questo caso non sarà necessario mappare tutte le URL nel file routes.php, infatti, tramite una convenzione, Laravel creerà automaticamente le rotte in base ai metodi pubblici della classe.

La convenzione prevede che i nomi del metodo siano composti dal nome del metodo HTTP seguiti dall'azione in camelCase e le rotte avranno come prefisso il nome del controller. Ad esempio il metodo getIndex del BookController verrà tradotto in una rotta GET all'URL /book (dato che "index" rappresenta la root) mentre il metodo postCreate verrà tradotto in una rotta POST all'URL /book/create.

Cachare le rotte

Se l'applicazione fa largo uso di rotte dinamiche definite tramite i metodi resource e controller, è buona norma quella di creare un file di cache per velocizzare il tempo di setup dell'applicazione (sulla documentazione ufficiale si parla addirittura di un risparmio di 100x). Basterà eseguire un php artisan route:cache per staticizzare la configurazione.

L'oggetto request

Una delle responsabilità dei controller è quella di agire sull'oggetto request. La miglior strategia per ottenere l'oggetto in questione è quella utilizzare la dependency injection di Laravel definendo un parametro tipizzato tra i parametri del metodo:

class DemoController extends BaseController
    public function dumpRequest(Illuminate\Http\Request $request) {
        var_dump($request);
    }
}

Una volta ottenuto l'oggetto, le funzionalità disponibili saranno molteplici.

Il metodo input dell'oggetto request permette appunto di leggere i parametri in ingresso. E' possibile passargli il nome del field da leggere ed eventualmente un parametro di default nel caso il parametro mancasse. Grazie invece al metodo all è possibile ottenere tutti i parametri.

$name = $request->input('name');
$email = $request->input('email', 'mail@domain.com');
$allParameters = $request->all();

Per ottenere un valore salvato in un cookie utilizziamo invece il metodo cookie:

$value = $request->cookie('cookieName');

L'oggetto response

La controparte dell'oggetto request è l'oggetto response. Quest'ultimo rappresenta appunto la risposta che il server invia al client. Normalmente i vari metodi mappati nel file delle rotte dovrebbero restituire un oggetto response, ma solitamente Laravel esegue il lavoro più complesso: quando restituiamo una semplice stringa, essa viene convertita automaticamente dal framework.

Il seguente entrypoint:

Route::get('/', function () {
    return 'Hello World';
});

Potrà essere scritto anche come:

use Illuminate\Http\Response;
Route::get('home', function () {
    return new Response('Hello World');
});

o, utilizzando l'helper response:

Route::get('home', function () {
    return response('Hello World');
});

Il vantaggio di utilizzare l'oggetto response è però quello di poter agire anche su altre proprietà come ad esempio gli header o i cookie:

return response('Hello World)
  ->header('Content-Type', 'text/plain')
  ->withCookie('myCookieName', 'myCookieValue');

Oltre agli header è possibile personalizzare il tipo di response. Possiamo per esempio restituire una view (che analizzeremo nel dettaglio nel prossimo articolo):

return response()->view('viewName', array('name' => 'Alberto'));

o un listato in notazione JSON:

return response()->json(array('name' => 'Alberto', 'skills' => array('PHP')));

o ancora restituire un listato in notazione JSON in modalità JSONP:

return response()->json(...)->setCallback($request->input('cb'));

o un file in modalità download:

return response()->download('file.pdf');

L'ultima responsabilità della response è quella di rispondere con una redirect. In questo caso si utilizza l'helper redirect. Nel primo esempio scriviamo l'URL manualmente:

return redirect('home/dashboard');

mentre in quest'altro utilizzeremo una rotta particolare:

return redirect(route('myRoute'));

Il primo controller della nostra applicazione

In questa terza parte relativa all'implementazione dell'applicazione Biblios svilupperemo alcuni controller di base. La loro implementazione sarà ancora una bozza in quanto per la versione definitiva dovremo prima parlare delle view. Modifichiamo quindi il comportamento della rotta / facendola puntare ad un metodo del nostro FrontendController:

Route::get('/', [ 'as' => 'home', 'uses' => 'FrontendController@getHome']);

Dato che la nostra applicazione conterrà un elenco di libri, possiamo già definire la seconda rotta parametrica che si occuperà di mostrare il dettaglio di un libro.

Route::get('/book/{id}', [ 'as' => 'bookDetail', 'uses' => 'FrontendController@getBookDetail']);

Implementiamo il nostro controller inserendo, temporaneamente, il contenuto direttamente nel codice in attesa del refactoring. Dato che stiamo per scrivere la nostra prima classe è necessario prima di tutto definire il namespace. Laravel ci offre un comando per impostare il namespace all'interno sia della applicazione che di Composer. Lanciamo quindi:

php artisan app:name Biblios

Una volta definito il nostro scope, creiamo il controller:

namespace Biblios\Http\Controllers;
class FrontendController extends Controller {
	public function getHome() {
		return "Io sono la homepage";
	}
	public function getBookDetail($id) {
		return "Io sono il dettaglio del libro " . $id;
	}
}

I controller sono come al solito testabili tramite il comando php artisan serve. Una volta avviato sarà possibile navigare su http://localhost:8000 e http://localhost:8000/book/123.

Ti consigliamo anche