Symfony 4: funzionamento e gestione di una richiesta

Ora che abbiamo creato un progetto Symfony 4 funzionante, possiamo vedere finalmente cosa c’è in questo scatolone magico.

Il pattern MVC

Se non siete proprio degli esperti e vi state approcciando ad un framework per la prima volta, probabilmente siete abituati a creare un file PHP per ogni pagina del sito, contenente un mix di logica e stampe a video. Certo funziona, ma è un metodo un po’ confusionario.
In informatica è bene praticare sempre il principio di Separation of Concerns (SoC), secondo cui ogni funzionalità deve essere isolata dalle altre. Invece di tenere in un’unica pagina query, logica, stampe a video, non sarebbe bello separare ognuno di questi aspetti?
Il pattern architetturale MVC, su cui Symfony è basato, rispetta a pieno il principio SoC. Separa l’applicazione nei tre componenti fondamentali, da cui prende il nome, Model View Controller. In breve:

  • Il Controller riceve i comandi dall’utente e comunica al Model cosa fare;
  • Il Model si occupa della logica e di preparare i dati necessari, ad esempio effettuando query al database;
  • La View riceve i dati estrapolati dal Model e li visualizza;

Per fare un esempio pratico, supponete di voler visualizzare l’articolo di un blog. Il Controller individua la richiesta fatta tramite la URL (il comando dell’utente) e chiede al Model di estrarre l’articolo dal database, il quale viene passato alla View e renderizzato.

Il filesystem

Ora che per sommi capi sappiamo cosa aspettarci, diamo un’occhiata alle directory di primo livello nel progetto:

$ ls -d */
bin/ config/ public/ src/ templates/ var/ vendor/

bin è una cartella su cui probabilmente non dovrete mai metterete le mani, ma contiene console, un’applicazione per la linea di comando che userete abbondantemente;

config contiene dei file di configurazione che riguardano le rotte, i servizi e i package che installarete;

public è la root del progetto e contiene essenzialmente index.php, il front controller del framework, ossia il primo file che viene eseguito da Symfony e che spiegherò a breve. Inoltre la directory contiene gli asset del progetto (ovvero i file statici, come css, js e le immagini); nelle edizioni precedenti la directory public si chiamava web e il file index.php era app.php;

src contiene i file su cui lavorerete di più, perché sono quelli che contengono il codice che determina il comportamento dell’applicazione; in pratica contiene parti del codice corrispondente ai componenti Controller e Model del pattern MVC;

templates contiene le viste, che come intuirete costituiscono il componente View;

var contiene i file di log e di cache;

vendor tecnicamente non c’entra con Symfony, ma con Composer, il gestore di pacchetti che ormai è uno strumento essenziale per questo framework. In sostanza questa directory contiene le dipendenze del progetto, come i Symfony Components, di cui abbiamo parlato nell’articolo introduttivo.

Rispetto alle edizioni precedenti, concettualmente non è cambiato molto, ma seppure Symfony 4 abbia riorganizzato leggermente il filesystem, secondo me il miglioramento è stato enorme. Il concetto di bundle è stato ridimensionato e ogni file si trova nel punto più “naturale”.

Gestione di una nuova richiesta

Un altro pattern fondamentale su cui è basato il framework è quello del front controller. Si tratta di un punto centralizzato attraverso cui passa ogni richiesta HTTP. Questo vuol dire che, indipendentemente dalla pagina che state visitando, il primo file ad essere richiamato sarà sempre lo stesso, che in Symfony 4 è public/index.php. In queste tre righe del file troviamo un po’ l’essenza di quello che succede:

$kernel = new Kernel($env, $debug);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);

Dopo che è stato creato l’oggetto Kernel, che si occupa di caricare configurazioni e package del progetto, viene istanziato Request, un oggetto PHP che conterrà le informazioni che troviamo tipicamente nell’header e nel body della richiesta HTTP.

A questo punto, l’oggetto Kernel prende in carico l’oggetto Request (con il metodo handle()) e attraverso il sistema di routing individua la Action (la porzione di codice scritta dall’utente sviluppatore) da eseguire. Infine, la risposta HTTP del server è organizzata nell’oggetto Response, che contiene informazioni come lo status HTTP e l’HTML da renderizzare sul browser.

Principio di funzionamento

L’insieme di front controller, Kernel e Action costituiscono il componente Controller del pattern MVC.

Nel prossimo articolo metteremo finalmente mano al codice, per vedere come creare nuove pagine per la nostra webapp.