Table of Contents
Questions & Feedback
Found a typo or an error?
Want to improve this document? Edit it.
Need support or have a technical question?
Post to the user mailing-list.
Master Symfony2 fundamentals
Symfony hosting done right
Discover the SensioLabs Support
L'architettura
- Quick Tour
- The Big Picture
- The View
- The Controller
- The Architecture
L'architettura¶
Sei un eroe! Chi avrebbe pensato che tu fossi ancora qui dopo le prime tre parti? I tuoi sforzi saranno presto ricompensati. Le prime tre parti non danno uno sguardo approfondito all'architettura del framework. Poiché essa rende unico Symfony2 nel panorama dei framework, vediamo in cosa consiste.
Capire la struttura delle cartelle¶
La struttura delle cartelle di un'applicazione Symfony2 è alquanto flessibile, ma la struttura delle cartelle della distribuzione Standard Edition riflette la struttura tipica e raccomandata di un'applicazione Symfony2:
app/: La configurazione dell'applicazione;src/: Il codice PHP del progetto;vendor/: Le dipendenze di terze parti;web/: La cartella radice del web.
La cartella web/¶
La cartella radice del web è la casa di tutti i file pubblici e statici, come immagini, fogli di stile, file JavaScript. È anche il posto in cui stanno i front controller:
1 2 3 4 5 6 7 8 9 | // 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 kernel inizialmente richiede il file bootstrap.php.cache, che lancia
l'applicazione e registra l'autoloader (vedi sotto).
Come ogni front controller, app.php usa una classe Kernel, AppKernel,
per inizializzare l'applicazione.
La cartella app/¶
La classe AppKernel è il punto di ingresso principale della configurazione
dell'applicazione e quindi è memorizzata nella cartella app/.
Questa classe deve implementare due metodi:
registerBundles()deve restituire un array di tutti i bundle necessari per eseguire l'applicazione;registerContainerConfiguration()carica la configurazione dell'applicazione (approfondito più avanti);
Il caricamento automatico essere configurato tramite Composer, che vuol dire che si
può usare qualsiasi classe PHP senza dover far nulla! Se occorre maggiore flessibilità,
si può estendere l'autoloader nel file app/autoload.php. Tutte le dipendenze sono
memorizzate sotto la cartella vendor/, ma è solo una convenzione.
Si possono memorizzare dove si preferisce, globalmente sul poprio server o localmente
nei propri progetti.
Note
Se si vuole approfondire l'argomento flessibilità dell'autoloader di Symfony2, leggere Composer-Autoloader. Symfony dispone anche di un componente specifico, si veda "Il componente ClassLoader".
Capire il sistema dei bundle¶
Questa sezione è un'introduzione a una delle più grandi e potenti caratteristiche di Symfony2, il sistema dei bundle.
Un bundle è molto simile a un plugin in un altro software. Ma perché allora si chiama bundle e non plugin? Perché ogni cosa è un bundle in Symfony2, dalle caratteristiche del nucleo del framework al codice scritto per la propria applicazione. I bundle sono cittadini di prima classe in Symfony2. Essi forniscono la flessibilità di usare delle caratteristiche pre-costruite impacchettate in bundle di terze parti o di distribuire i propri bundle. Questo rende molto facile scegliere quali caratteristiche abilitare nella propria applicazione e ottimizzarle nel modo preferito. A fine giornata, il codice della propria applicazione è importante quanto il nucleo stesso del framework.
Registrare un bundle¶
Un'applicazione è composta di bundle, come definito nel metodo registerBundles()
della classe AppKernel . Ogni bundle è una cartella che contiene una singola classe
Bundle che la descrive:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // app/AppKernel.php
public function registerBundles()
{
$bundles = array(
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),
);
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
$bundles[] = new Acme\DemoBundle\AcmeDemoBundle();
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
}
return $bundles;
}
|
Oltre a AcmeDemoBundle, di cui abbiamo già parlato, si noti che il kernel
abilita anche FrameworkBundle, DoctrineBundle,
SwiftmailerBundle e AsseticBundle. Fanno tutti parte del nucleo del
framework.
Configurare un bundle¶
Ogni bundle può essere personalizzato tramite file di configurazione scritti in YAML, XML o PHP. Si veda la configurazione predefinita:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | # app/config/config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
framework:
#esi: ~
#translator: { fallback: "%locale%" }
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: "%kernel.debug%"
form: true
csrf_protection: true
validation: { enable_annotations: true }
templating: { engines: ['twig'] } #assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_proxies: ~
session: ~
# Configurazione di Twig
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
# Configurazione di Assetic
assetic:
debug: "%kernel.debug%"
use_controller: false
bundles: [ ]
# java: /usr/bin/java
filters:
cssrewrite: ~
# closure:
# jar: "%kernel.root_dir%/Resources/java/compiler.jar"
# yui_css:
# jar: "%kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar"
# Configurazione di Doctrine
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
orm:
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
# Configurazione di Swiftmailer
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool: { type: memory }
|
Ogni voce come framework definisce la configurazione per uno specifico bundle.
Per esempio, framework configura FrameworkBundle, mentre swiftmailer
configura SwiftmailerBundle.
Ogni ambiente può sovrascrivere la configurazione predefinita, fornendo un file
di configurazione specifico. Per esempio, l'ambiente dev carica il file config_dev.yml,
che carica la configurazione principale (cioè config.yml) e quindi la modifica per
aggiungere alcuni strumenti di debug:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # app/config/config_dev.yml
imports:
- { resource: config.yml }
framework:
router: { resource: "%kernel.root_dir%/config/routing_dev.yml" }
profiler: { only_exceptions: false }
web_profiler:
toolbar: true
intercept_redirects: false
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
firephp:
type: firephp
level: info
assetic:
use_controller: true
|
Estendere un bundle¶
Oltre a essere un modo carino per organizzare e configurare il proprio codice, un bundle
può estendere un altro bundle. L'ereditarietà dei bundle consente di sovrascrivere un bundle
esistente, per poter personalizzare i suoi controllori, i template o qualsiasi altro suo
file. Qui sono d'aiuto i nomi logici (come @AcmeDemoBundle/Controller/SecuredController.php),
che astraggono i posti in cui le risorse sono effettivamente memorizzate.
Nomi logici di file¶
Quando si vuole fare riferimento a un file da un bundle, usare questa notazione:
@NOME_BUNDLE/percorso/del/file; Symfony2 risolverà @NOME_BUNDLE nel percorso
reale del bundle. Per esempio, il percorso logico
@AcmeDemoBundle/Controller/DemoController.php verrebbe convertito in
src/Acme/DemoBundle/Controller/DemoController.php, perché Symfony conosce
la locazione di AcmeDemoBundle.
Nomi logici di controllori¶
Per i controllori, occorre fare riferimento ai nomi dei metodi usando il formato
NOME_BUNDLE:NOME_CONTROLLORE:NOME_AZIONE. Per esempio,
AcmeDemoBundle:Welcome:index mappa il metodo indexAction della classe
Acme\DemoBundle\Controller\WelcomeController.
Nomi logici di template¶
Per i template, il nome logico AcmeDemoBundle:Welcome:index.html.twig è
convertito al percorso del file src/Acme/DemoBundle/Resources/views/Welcome/index.html.twig.
I template diventano ancora più interessanti quando si realizza che i file non
hanno bisogno di essere memorizzati su filesystem. Si possono facilmente
memorizzare, per esempio, in una tabella di una base dati.
Estendere i bundle¶
Se si seguono queste convenzioni, si può usare
l'ereditarietà dei bundle
per "sovrascrivere" file, controllori o template. Per esempio, se un nuovo bundle
chiamato AcmeNewBundle estende AcmeDemoBundle, Symfony proverà a caricare
prima il controllore AcmeDemoBundle:Welcome:index da AcmeNewBundle e poi
cercherà il secondo AcmeDemoBundle. Questo vuol dire che un bundle può sovrascrivere
quasi ogni parte di un altro bundle!
Capite ora perché Symfony2 è così flessibile? Condividere i propri bundle tra le applicazioni, memorizzarli localmente o globalmente, a propria scelta.
Usare i venditori¶
Probabilmente la propria applicazione dipenderà da librerie di terze parti.
Queste ultime dovrebbero essere memorizzate nella cartella vendor/.
Tale cartella contiene già le librerie di Symfony2, SwiftMailer, l'ORM Doctrine,
il sistema di template Twig e alcune altre librerie e bundle di terze parti.
Capire la cache e i log¶
Symfony2 è forse uno dei framework completi più veloci in circolazione.
Ma come può essere così veloce, se analizza e interpreta decine di file
YAML e XML a ogni richiesta? In parte, per il suo sistema di cache. La
configurazione dell'applicazione è analizzata solo per la prima richiesta
e poi compilata in semplice file PHP, memorizzato nella cartella app/cache/
dell'applicazione. Nell'ambiente di sviluppo, Symfony2 è abbastanza
intelligente da pulire la cache quando cambiano dei file. In produzione, invece,
occorre pulire la cache manualmente quando si aggiorna il codice o si modifica la configurazione.
Sviluppando un'applicazione web, le cose possono andar male in diversi modi.
I file di log nella cartella app/logs/ dicono tutto a proposito delle richieste
e aiutano a risolvere il problema in breve tempo.
Usare l'interfaccia a linea di comando¶
Ogni applicazione ha uno strumento di interfaccia a linea di comando (app/console),
che aiuta nella manutenzione dell'applicazione. La console fornisce dei comandi che incrementano la produttività, automatizzando
dei compiti noiosi e ripetitivi.
Richiamandola senza parametri, si può sapere di più sulle sue capacità:
1 | $ php app/console
|
L'opzione --help aiuta a scoprire l'utilizzo di un comando:
1 | $ php app/console router:debug --help
|
Considerazioni finali¶
Dopo aver letto questa parte, si dovrebbe essere in grado di muoversi facilmente dentro Symfony2 e farlo funzionare. Ogni cosa in Symfony2 è fatta per rispondere alle varie esigenze. Quindi, si possono rinominare e spostare le varie cartelle, finché non si raggiunge il risultato voluto.
E questo è tutto per il giro veloce. Dai test all'invio di email, occorre ancora imparare diverse cose per padroneggiare Symfony2. Pronti per approfondire questi temi? Senza indugi, basta andare nella pagine del libro e scegliere un argomento a piacere.





is a trademark of Fabien Potencier. All rights reserved.