Creare pagine in Symfony¶
La creazione di una nuova pagina in Symfony, che si tratti di una pagina HTML o di un JSON, è un semplice processo in due passi:
- Creare una rotta: Una rotta definisce l’URL (p.e.
/about
) verso la pagina e specifica un controllore; - Creare un controllore: Un controllore è una funzione PHP, che costruisce la pagina. Si
prende la richiesta in entrata e la si trasforma in un oggetto
Response
di Symfony, che contiene HTML, una stringa JSON o altro.
Proprio come sul web, ogni interazione sul web inizia con una richiesta HTTP. Il lavoro di un’applicazione è semplicemente quello di interpretare la richiesta e restituire l’appropriata risposta.
Ambienti e front controller¶
Ogni applicazione Symfony gira in un ambiente. Un ambiente
è un insieme specifico di configurazioni e bundle caricati, rappresentato da una stringa.
La stessa applicazione può girare con diverse configurazioni, se eseguita
in diversi ambienti. Symfony dispone di tre ambienti
predefiniti: dev
, test
e prod
. È comunque possibile crearne di altri.
Gli ambienti sono utili, perché consentono a una singola applicazione di avere un ambiente (dev)
pensato per il debug e un altro (prod) ottimizziato per la velocità. Si possono
anche caricare bundle specifici, in base all’ambiente. Per esempio,
Symfony dispone di un WebProfilerBundle (descritto più avanti), abilitato
solamente in dev
e in test
.
Symfony dispone di due front controller pubblici: app_dev.php
fornisce l’ambiente dev
, mentre app.php
fornisce l’ambiente prod
.
Ogni accesso via web a Symfony normalmente passa per uno di questi due front controller.
(L’ambiente test
normalmente si usa solo quando si eseguono i test e quindi
non dispone di un front controller dedicato. La linea di comando fornisce ugualmente
un front controller utilizzabile con qualsiasi ambiente.)
Quando il front controller inizializza il kernel, fornisce due parametri:
l’ambiente e la modalità di debug con cui il kernel deve girare.
Per far rispondere velocemente l’applicazione, Symfony mantiene una cache sotto la
cartella app/cache/
. Quando il debug è abilitato (come in app_dev.php
),
la cache viene rinfrescata automaticamente a ogni modifica del
codice o della configurazione. In debug, Symfony va più
lentamente, ma le modifiche sono rispettate senza dover pulire a mano la
cache.
La pagina “numero casuale”¶
In questo capitolo, svilupperemo un’applicazione per generare numeri casuali.
Quando avremo finito, l’utente sarà in grado di ottenere un numero casuale tra 1
e il limite superiore, impostato da URL:
http://localhost/app_dev.php/random/100
In realtà, si potrà sostituire 100
con qualsiasi altro numero, che funga da limite
superiore per il numero da generare. Per creare la pagina, seguiamo il semplice processo
in due passi.
Note
La guida presume che Symfony sia stato già scaricato e il server web
configurato. L’URL precedente presume che localhost
punti alla cartella
web
del nuovo progetto Symfony. Per informazioni dettagliate su
questo processo, vedere la documentazione del server web usato.
Ecco le pagine di documentazione per alcuni server web:
- Per il server Apache, fare riferimento alla documentazione su DirectoryIndex di Apache.
- Per Nginx, fare riferimento alla documentazione su HttpCoreModule di Nginx.
Prima di iniziare: creare il bundle¶
Prima di iniziare, occorrerà creare un bundle. In Symfony, un bundle è come un plugin, tranne per il fatto che tutto il codice nella propria applicazione starà dentro a un bundle.
Un bundle non è nulla di più di una cartella che ospita ogni cosa correlata a una specifica caratteristica, incluse classi PHP, configurazioni e anche fogli di stile e file JavaScript (si veda Il sistema dei bundle).
A seconda della modalità di installazione di Symfony, si potrebbe già a vere un bundle, chiamato
AcmeDemoBundle. Controllare nella cartella src/
del progetto se c’è
una cartella DemoBundle/
sotto la cartella Acme/
. Se tali
cartelle esistono, saltare il resto di questa sezione e andare direttamente alla
creazione della rotta.
Per creare un bundle chiamato AcmeHelloBundle
(un bundle creato appositamente in
questo capitolo), eseguire il seguente comando e seguire le istruzioni su schermo
(usando tutte le opzioni predefinite):
$ php app/console generate:bundle --namespace=Acme/DemoBundle --format=yml
Dietro le quinte, viene creata una cartella per il bundle in src/Acme/DemoBundle
.
Inoltre viene aggiunta automaticamente una riga al file app/AppKernel.php
, in modo
che il bundle sia registrato nel kernel:
// app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new Acme\DemoBundle\AcmeDemoBundle(),
);
// ...
return $bundles;
}
Ora che si è impostato il bundle, si può iniziare a costruire la propria applicazione, dentro il bundle stesso.
Passo 1: creare la rotta¶
Per impostazione predefinita, il file di configurazione delle rotte in un’applicazione
Symfony si trova in app/config/routing.yml
. Come ogni configurazione in Symfony,
si può anche scegliere di usare XML o PHP per configurare le rotte.
Se si guarda il file principale delle rotte, si vedrà che Symfony ha già aggiunto una voce, quando è stato generato AcmeDemoBundle:
Questa voce è molto basica: dice a Symfony di caricare la configurazione delle rotte
dal file Resources/config/routing.yml
(routing.xml
o routing.php
rispettivamente negli esempi di codice XML e PHP), che si trova dentro
AcmeDemoBundle. Questo vuol dire che si mette la configurazione delle rotte direttamente in
app/config/routing.yml
o si organizzano le proprie rotte attraverso la propria applicazione
e le si importano da qui.
Note
Non si è limitati a caricare configurazioni di rotte che condividono lo stesso formato. Per esempio, si potrebbe anche caricare un file YAML in una configurazione XML e viceversa.
Ora che il file routing.yml
del bundle è stato importato, aggiungere la nuova rotta,
che definisce l’URL della pagina che stiamo per creare:
Il routing consiste di due pezzi di base: il percorso (path
), che è l’URL
a cui la rotta corrisponderà, e un array defaults
, che specifica il controllore
che sarà eseguito. La sintassi dei segnaposto nello schema ({limit}
) è un jolly.
Vuol dire che /random/10
, /random/327
o ogni altro URL simile
corrisponderanno a questa rotta. Il parametro del segnaposto {limit}
sarà anche
passato al controllore, in modo da poter usare il suo valore per salutare personalmente
l’utente.
Note
Il sistema delle rotte ha molte altre importanti caratteristiche per creare strutture di URL flessibili e potenti nella propria applicazioni. Per maggiori dettagli, si veda il capitolo dedicato alle Rotte.
Passo 2: creare il controllore¶
Quando un URL come /hello/Ryan
viene gestita dall’applicazione, la rotta hello
viene corrisposta e il controllore AcmeDemoBundle:Hello:index
eseguito dal
framework. Il secondo passo del processo di creazione della pagina è quello di creare
tale controllore.
Il controllore ha il nome logico AcmeDemoBundle:Random:index
ed è mappato
sul metodo indexAction
di una classe PHP chiamata
Acme\DemoBundle\Controller\RandomController
. Iniziamo creando questo file dentro
il nostro AcmeDemoBundle:
// src/Acme/DemoBundle/Controller/RandomController.php
namespace Acme\DemoBundle\Controller;
class RandomController
{
}
In realtà, il controllore non è nulla di più di un metodo PHP, che va creato e che
Symfony eseguirà. È qui che il codice usa l’informazione dalla richiesta per
costruire e preparare la risorsa che è stata richiesta. Tranne per alcuni casi avanzati,
il prodotto finale di un controllore è sempre lo stesso: un oggetto Response
di
Symfony.
Creare il metodo indexAction
, che Symfony eseguirà quando la rotta hello
sarà
corrisposta:
// src/Acme/DemoBundle/Controller/RandomController.php
namespace Acme\DemoBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class RandomController
{
public function indexAction($limit)
{
return new Response(
'<html><body>Numero: '.rand(1, $limit).'</body></html>'
);
}
}
Il controllore è semplice: esso crea un nuovo oggetto Response
, il cui primo
parametro è il contenuto che sarà usato dalla risposta (in questo esempio, una
piccola pagina HTML).
Congratulazioni! Dopo aver creato solo una rotta e un controllore, abbiamo già una pagina pienamente funzionante! Se si è impostato tutto correttamente, la propria applicazione dovrebbe salutare:
http://localhost/app_dev.php/random/10
Tip
Si può anche vedere l’applicazione nell’ambiente “prod”, visitando:
http://localhost/app.php/random/10
Se si ottiene un errore, è probabilmente perché occorre pulire la cache, eseguendo:
$ php app/console cache:clear --env=prod --no-debug
Un terzo passo, facoltativo ma comune, del processo è quello di creare un template.
Note
I controllori sono il punto principale di ingresso del codice e un ingrediente chiave della creazione di pagine. Si possono trovare molte più informazioni nel capitolo sul controllore.
Passo 3 (facoltativo): creare il template¶
I template consentono di spostare tutta la presentazione (p.e. il codice HTML) in un file separato e riusare diverse porzioni del layout della pagina. Invece di scrivere il codice HTML dentro al controllore, meglio rendere un template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // src/Acme/DemoBundle/Controller/RandomController.php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class RandomController extends Controller
{
public function indexAction($limit)
{
$number = rand(1, $limit);
return $this->render(
'AcmeDemoBundle:Random:index.html.twig',
array('number' => $number)
);
// rende invece un template PHP
// return $this->render(
// 'AcmeDemoBundle:Random:index.html.php',
// array('number' => $number)
// );
}
}
|
Note
Per poter usare il metodo :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::render`,
il controllore deve estendere la classe
Symfony\Bundle\FrameworkBundle\Controller\Controller
,
che aggiunge scorciatoie per compiti comuni nei controllori. Ciò viene fatto
nell’esempio precedente aggiungendo l’istruzione use
alla riga 4 ed
estendendo Controller
alla riga 6.
Il metodo render()
crea un oggetto Response
riempito con il contenuto del
template dato. Come ogni altro controllore, alla fine l’oggetto Response
viene restituito.
Si noti che ci sono due diversi esempi su come rendere il template. Per impostazione predefinita, Symfony supporta due diversi linguaggi di template: i classici template PHP e i template, concisi ma potenti, Twig. Non ci si allarmi, si è liberi di scegliere tra i due, o anche tutti e due nello stesso progetto.
Il controllore rende il template AcmeDemoBundle:Hello:index.html.twig
,
che usa la seguente convenzioni dei nomi:
NomeBundle:NomeControllore:NomeTemplate
Questo è il nome logico del template, che è mappato su una locazione fisica, usando la seguente convenzione:
/percorso/di/NomeBundle/Resources/views/NomeControllore/NomeTemplate
In questo caso, AcmeHelloBundle
è il nome del bundle, Hello
è il
controllore e index.html.twig
il template:
Analizziamo il template Twig riga per riga:
- riga 2: Il token
extends
definisce un template padre. Il template definisce esplicitamente un file di layout, dentro il quale sarà inserito. - riga 4: Il token
block
dice che ogni cosa al suo interno va posta dentro un blocco chiamatobody
. Come vedremo, è responsabilità del template padre (base.html.twig
) rendere alla fine il blocco chiamatobody
.
Il template padre, ::base.html.twig
, manca delle porzioni NomeBundle
e NomeControllore del suo nome (per questo ha il doppio duepunti (::
)
all’inizio). Questo vuol dire che il template risiede fuori dai bundle, nella
cartella app
:
Il template di base definisce il layout HTML e rende il blocco body
, che era
stato definito nel template index.html.twig
. Rende anche un blocco title
,
che si può scegliere di definire nel template nel template index.html.twig
.
Poiché non è stato definito il blocco title
nel template figlio, il suo valore
predefinito è “Benvenuto!”.
I template sono un modo potente per rendere e organizzare il contenuto della propria pagina. Un template può rendere qualsiasi cosa, dal codice HTML al CSS, o ogni altra cosa che il controllore abbia bisogno di restituire.
Nel ciclo di vita della gestione di una richiesta, il motore dei template è solo
uno strumento opzionale. Si ricordi che lo scopo di ogni controllore è quello di
restituire un oggetto Response
. I template sono uno strumento potente, ma
facoltativo, per creare il contenuto per un oggetto Response
.
Struttura delle cartelle¶
Dopo solo poche sezioni, si inizia già a capire la filosofia che sta dietro alla creazione e alla resa delle pagine in Symfony. Abbiamo anche già iniziato a vedere come i progetti Symfony siano strutturati e organizzati. Alla fine di questa sezione, sapremo dove cercare e inserire i vari tipi di file, e perché.
Sebbene interamente flessibili, per impostazione predefinita, ogni applicazione Symfony ha la stessa struttura di cartelle raccomandata:
app/
- Questa cartella contiene la configurazione dell’applicazione;
src/
- Tutto il codice PHP del progetto sta all’interno di questa cartella;
vendor/
- Ogni libreria dei venditori è inserita qui, per convenzione;
web/
- Questa è la cartella radice del web e contiene ogni file accessibile pubblicamente;
See also
Si può facilmente ridefinire la struttura predefinita delle cartelle. Vedere /cookbook/configuration/override_dir_structure per maggiori informazioni.
La cartella web¶
La cartella radice del web è la casa di tutti i file pubblici e statici, inclusi immagini, fogli di stile, file JavaScript. È anche il posto in cui stanno tutti i front controller:
// web/app.php
require_once __DIR__.'/../app/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';
use Symfony\Component\HttpFoundation\Request;
$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
$kernel->handle(Request::createFromGlobals())->send();
Il file del front controller (app.php
in questo esempio) è il file PHP che viene
eseguito quando si usa un’applicazione Symfony e il suo compito è quello di usare una
classe kernel, AppKernel
, per inizializzare l’applicazione.
Tip
Aver un front controller vuol dire avere URL diverse e più flessibili rispetto a una tipica applicazione in puro PHP. Quando si usa un front controller, gli URL sono formattati nel modo seguente:
http://localhost/app.php/random/10
Il front controller, app.php
, viene eseguito e l’URL “interno”
/random/10
è dirottato internamente, usando la configurazione delle rotte.
Usando mod_rewrite
di Apache, si può forzare l’esecuzione del file app.php
senza bisogno di specificarlo nell’URL:
http://localhost/random/10
Sebbene i front controller siano essenziali nella gestione di ogni richiesta, raramente si avrà bisogno di modificarli o anche di pensarci. Saranno brevemente menzionati ancora nella sezione Ambienti.
La cartella dell’applicazione (app
)¶
Come visto nel front controller, la classe AppKernel
è il punto di ingresso principale
dell’applicazione ed è responsabile di tutta la configurazione. Per questo è memorizzata
nella cartella app/
.
Questa classe deve implementare due metodi, che definiscono tutto ciò di cui Symfony ha bisogno di sapere sulla propria applicazione. Non ci si deve preoccupare di questi metodi all’inizio, Symfony li riempie al posto nostro con delle impostazioni predefinite.
registerBundles()
- Restituisce un array di tutti bundle necessari per eseguire l’applicazione (vedere Il sistema dei bundle);
registerContainerConfiguration()
- Carica il file della configurazione principale dell’applicazione (vedere la sezione Configurazione dell’applicazione).
Nello sviluppo quotidiano, per lo più si userà la cartella app/
per modificare i
file di configurazione e delle rotte nella cartella app/config/
(vedere
Configurazione dell’applicazione). Essa contiene anche la cartella della cache
dell’applicazione (app/cache
), la cartella dei log (app/logs
) e la cartella
dei file risorsa a livello di applicazione, come i template (app/Resources
).
Ognuna di queste cartella sarà approfondita nei capitoli successivi.
La cartella dei sorgenti (src
)¶
Detto semplicemente, la cartella src/
contiene tutto il codice (codice PHP,
template, file di configurazione, fogli di stile, ecc.) che guida la propria
applicazione. Quando si sviluppa, gran parte del lavoro sarà svolto
dentro uno o più bundle creati in questa cartella.
Ma cos’è esattamente un bundle?
Configurazione dell’applicazione¶
Un’applicazione è composta da un insieme di bundle, che rappresentano tutte le
caratteristiche e le capacità dell’applicazione stessa. Ogni bundle può essere
personalizzato tramite file di configurazione, scritti in YAML, XML o PHP. Per
impostazione predefinita, il file di configurazione principale risiede nella cartella
app/config/
è si chiama config.yml
, config.xml
o config.php
, a seconda
del formato scelto:
Note
Vedremo esattamente come caricare ogni formato di file nella prossima sezione, Ambienti.
Ogni voce di primo livello, come framework
o twig
, definisce la configurazione
per un particolare bundle. Per esempio, la voce framework
definisce la configurazione
per il bundle del nucleo di Symfony FrameworkBundle e include configurazioni per
rotte, template e altri sistemi fondamentali.
Per ora, non ci preoccupiamo delle opzioni di configurazione specifiche di ogni sezione. Il file di configurazione ha delle opzioni predefinite impostate. Leggendo ed esplorando ogni parte di Symfony, le opzioni di configurazione specifiche saranno man mano approfondite.
Esportazione della configurazione predefinita¶
Si può esportare la configurazione predefinita per un bundle in yaml sulla console, usando
il comando config:dump-reference
. Ecco un esempio di esportazione della configurazione
predefinita di FrameworkBundle:
$ app/console config:dump-reference FrameworkBundle
Si può anche usare l’alias dell’estensione (voce di configurazione):
$ app/console config:dump-reference framework
Note
Vedere la ricetta /cookbook/bundles/extension per informazioni sull’aggiunta di configurazioni per un bundle.
Ambienti¶
Un’applicazione può girare in vari ambienti. I diversi ambienti condividono lo stesso
codice PHP (tranne per il front controller), ma usano differenti configurazioni.
Per esempio, un ambiente dev
salverà nei log gli avvertimenti e gli errori,
mentre un ambiente prod
solamente gli errori. Alcuni file sono ricostruiti a
ogni richiesta nell’ambiente dev
(per facilitare gli sviluppatori), ma salvati
in cache nell’ambiente prod
. Tutti gli ambienti stanno insieme nella stessa
macchina e sono eseguiti nella stessa applicazione.
Un progetto Symfony generalmente inizia con tre ambienti (dev
, test
e prod
), ma creare nuovi ambienti è facile. Si può vedere la propria applicazione
in ambienti diversi, semplicemente cambiando il front controller nel
browser. Per vedere l’applicazione in ambiente dev
, accedere all’applicazione
tramite il front controller di sviluppo:
http://localhost/app_dev.php/random/10
Se si preferisce vedere come l’applicazione si comporta in ambiente di produzione,
richiamare invece il front controller prod
:
http://localhost/app.php/random/10
Essendo l’ambiente prod
ottimizzato per la velocità, la configurazione, le
rotte e i template Twig sono compilato in classi in puro PHP e messi in cache.
Per vedere delle modifiche in ambiente prod
, occorrerà pulire tali file
in cache e consentire che siano ricostruiti:
$ php app/console cache:clear --env=prod --no-debug
Note
Se si apre il file web/app.php
, si troverà che è configurato esplicitamente
per usare l’ambiente prod
:
$kernel = new AppKernel('prod', false);
Si può creare un nuovo front controller per un nuovo ambiente, copiando questo
file e cambiando prod
con un altro valore.
Note
L’ambiente test
è usato quando si eseguono i test automatici e non può
essere acceduto direttamente tramite il browser. Vedere il
capitolo sui test per maggiori dettagli.
Configurazione degli ambienti¶
La classe AppKernel
è responsabile del caricare effettivamente i file
di configurazione scelti:
// app/AppKernel.php
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(
__DIR__.'/config/config_'.$this->getEnvironment().'.yml'
);
}
Sappiamo già che l’estensione .yml
può essere cambiata in .xml
o
.php
, se si preferisce usare XML o PHP per scrivere la propria configurazione.
Si noti anche che ogni ambiente carica i propri file di configurazione. Consideriamo
il file di configurazione per l’ambiente dev
.
La voce imports
è simile all’istruzione include
di PHP e garantisce
che il file di configurazione principale (config.yml
) sia caricato per primo.
Il resto del file gestisce la configurazione per aumentare il livello di log, oltre
ad altre impostazioni utili all’ambiente di sviluppo.
Sia l’ambiente prod
che quello test
seguono lo stesso modello: ogni ambiente
importa il file di configurazione di base e quindi modifica i suoi file di configurazione
per soddisfare le esigenze dello specifico ambiente. Questa è solo una convenzione, ma
consente di riusare la maggior parte della propria configurazione e personalizzare solo
le parti diverse tra gli ambienti.
Riepilogo¶
Congratulazioni! Ora abbiamo visto ogni aspetto fondamentale di Symfony e scoperto quanto possa essere facile e flessibile. Pur essendoci ancora moltissime caratteristiche da scoprire, assicuriamoci di tenere a mente alcuni aspetti fondamentali:
- creare una pagine è un processo in tre passi, che coinvolge una rotta, un controllore e (opzionalmente) un template.
- ogni progetto contiene solo alcune cartelle principali:
web/
(risorse web e front controller),app/
(configurazione),src/
(i propri bundle) evendor/
(codice di terze parti) (c’è anche la cartellabin/
, usata per aiutare nell’aggiornamento delle librerie dei venditori); - ogni caratteristica in Symfony (incluso in nucleo del framework stesso) è organizzata in bundle, insiemi strutturati di file relativi a tale caratteristica;
- la configurazione per ciascun bundle risiede nella cartella
app/config
e può essere specificata in YAML, XML o PHP; - la configurazione dell’applicazione globale si trova nella cartella
app/config
; - ogni ambiente è accessibile tramite un diverso front controller (p.e.
app.php
eapp_dev.php
) e carica un diverso file di configurazione.
Da qui in poi, ogni capitolo introdurrà strumenti sempre più potenti e concetti sempre più avanzati. Più si imparerà su Symfony, più si apprezzerà la flessibilità della sua architettura e la potenza che dà nello sviluppo rapido di applicazioni.