Il framework Symfony è basato sul modello MVC (Model-View-Controller) riportato nella figura di seguito.
L'architettura MVC è costruita su tre livelli:
- Model: fornisce i metodi con cui accedere ai dati utili all'applicazione;
- View: si occupa di rendere disponibile i dati contenuti nel model all'utente attraverso un'interfaccia costituita da una pagina web;
- Controller: il suo compito è quello di ricevere i comandi dell'utente e modificare di conseguenza lo stato del model e del view.
Questa architettura, separando logicamente il model (business logic) dal view (presentation), da una parte rende possibile la distribuzione dell'applicazione su sistemi diversi (browser diversi, personal computer, palmari, smart phone, etc.) semplicemente implementando per ciascuno di essi il solo livello view e utilizzando per tutti gli stessi livelli model e controller, dall'altra consente di utilizzare diverse basi di dati (MySQL, Oracle, SQL Server, ecc. ecc.) implementando per ciascuna di esse un diverso model e utilizzando gli stessi view e controller.
Si capisce quindi come un'architettura di questo genere permetta una maggiore manutenibilità dell'applicativo oltre a una maggiore riutilizzazione del codice e una maggiore scalabilità del prodotto. L'implementazione del modello MVC in Symfony è illustrato nella figura seguente.
Come si può vedere il model è suddiviso in due parti: Data Access e DB Astraction; il view è composto da Layout, View Logic e Template e, infine, il controller è formato da Front Controller e Action.
Al momento della creazione di un nuovo progetto Symfony genera automaticamente tutti gli script PHP necessari per l'implementazione del modello MVC, basandosi sulla struttura del data base. In particolare le classi del model vengono generate automaticamente basandosi sulla struttura del data base per mezzo di una libreria chiamata Propel, il cui compito è quello di fornire lo scheletro delle classi e il loro codice. L'astrazione del database è invisibile allo sviluppatore, in quanto gestita da un componente chiamato Creole e, se si dovesse cambiare il motore del data base non c'è bisogno di modificare nessuna riga del codice: basta semplicemente modificare un parametro di configurazione.
Prima di analizzare in dettaglio il modello MVC in Symfony, vediamo subito un esempio: provate a confrontare il codice di un semplice progetto per la gestione di una rubrica scritto sia senza l'utilizzo del modello MVC (flat) sia prodotto attraverso Symfony.
Listato 1: Uno script flat
<?php // Connessione al data base $link = mysql_connect('localhost', 'myuser', 'mypassword'); mysql_select_db('rubrica_db', $link); // Query SQL $result = mysql_query('SELECT cognome, nome, telefono FROM contatti', $link); ?> <html> <head><title>Rubrica</title></head> <body> <h1>Contatti</h1> <table> <tr><th>Cognome</th><th>Nome</th><th>Telefono</th></tr> <?php // Mostra i risultati in formato HTML while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { echo "\t<tr>\n"; printf("\t\t<td> %s </td>\n", $row['cognome']); printf("\t\t<td> %s </td>\n", $row['nome']); printf("\t\t<td> %s </td>\n", $row['telefono']); echo "\t</tr>\n"; } ?> </table> </body> </html> <?php // Chiusura della connessione mysql_close($link); ?>
Listato 2.1: Il Controller, index.php
<?php
// Richiesta del model
require_once('model.php');
// Recupero del risultato della query
$posts = getAllPosts();
// Richiesta del view
require('view.php');
?>
Listato 2.2: La Vista, view.php
<html> <head> <title>Rubrica</title> </head> <body> <h1>Contatti</h1> <table> <tr><th>Cognome</th><th>Nome</th><th>Telefono</th></tr> <?php foreach ($posts as $post): ?> <tr> <td><?php echo $post['cognome'] ?></td> <td><?php echo $post['nome'] ?></td> <td><?php echo $post['telefono'] ?></td> </tr> <?php endforeach; ?> </table> </body> </html>
Listato 2.3: Il Modello, model.php
<?php
function getAllPosts()
{
// Connessione al data base
$link = mysql_connect('localhost', 'myuser', 'mypassword');
mysql_select_db('rubrica_db', $link);
// Query SQL
$result = mysql_query('SELECT cognome, nome, telefono FROM contatti', $link);
// Salva il risultato della query in un array
$posts = array();
while ($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
$posts[] = $row;
}
// Chiusura della connessione
mysql_close($link);
return $posts;
}
?>
Come si può facilmente notare, il compito del controller è quello di prendere i dati dal model e passarli al view, il model si occupa dell'accesso ai dati e il view si occupa della presentazione del risultato ottenuto.