diff --git a/gentle-introduction/it/02-Exploring-Symfony-s-Code.markdown b/gentle-introduction/it/02-Exploring-Symfony-s-Code.markdown index bd922e6..2bcc7f8 100644 --- a/gentle-introduction/it/02-Exploring-Symfony-s-Code.markdown +++ b/gentle-introduction/it/02-Exploring-Symfony-s-Code.markdown @@ -1,15 +1,15 @@ Capitolo 2 - Esplorazione del codice di symfony =============================================== -In un primo momento l'esplorazione del codice alla base di un applicativo scritto utillizzando symfony può sembrare scoraggiante. -Il codice è costituito da molteplici directory e script, i vari file sono un mix di classi PHP, HTML e a volte una combinazione di entrambi. -Capiterà anche di trovare riferimenti a classi che non sono presenti all'interno della directory -dell'applicativo oppure constatare che si può arrivare ad una profondità delle directory di ben sei livelli. +In un primo momento l'esplorazione del codice alla base di un applicativo scritto utilizzando symfony può sembrare scoraggiante. +Il codice è costituito da molteplici cartelle e script, i vari file sono un mix di classi PHP, HTML e a volte una combinazione di entrambi. +Capiterà anche di trovare riferimenti a classi che non sono presenti all'interno della cartella +dell'applicativo oppure constatare che si può arrivare a una profondità delle cartelle di ben sei livelli. Ma una volta compresa la ragione di questa apparente complessità, ci si sentirà talmente a proprio agio che non si vorrebbe assolutamente cambiare la struttura dell'applicativo symfony con nessun'altra. Pattern MVC ---------------- +----------- Symfony è basato sul classico web design pattern conosciuto come architettura MVC, che consiste di tre livelli: @@ -35,15 +35,15 @@ Figure 2-1 - Il pattern MVC ### I livelli dell'MVC Per comprendere i vantaggi del pattern MVC, verrà illustrato di seguito come convertire un'applicazione base PHP -nel sudetto pattern architetturale. -Un perfetto esempio e' dato da una lista di post di un web blog. +nel suddetto pattern architetturale. +Un perfetto esempio è dato da una lista di post di un web blog. #### Programmazione "piatta" Se si volesse mostrare una lista di record estratti da un database utilizzando un unico script PHP si utilizzerebbe del codice simile a quello mostrato nel Listato 2-1 -Listing 2-1 - Un'unico Script +Listato 2-1 - Un'unico Script [php] @@ -91,9 +91,9 @@ I maggiori problemi che si possono incontrare utilizzando questo codice e questo * Non è presente un controllo degli errori (cosa succederebbe se la connessione al db fallisse?) * Codice HTML e codice PHP mischiati e intrecciati tra di loro. - * Il codice e' legato al database MYSQL. + * Il codice è legato al database MYSQL. -#### Isolare la Presentazione +#### Isolare la presentazione Le chiamate `echo` e `printf` presenti nel Listato 2-1 rendono il codice difficile da leggere. Diventerebbe un'operazione onerosa e complessa modificare il codice HTML per migliorarne la presentazione. @@ -149,8 +149,8 @@ Listato 2-3 - La Vista, in `view.php` Una buona regola per determinare se la vista è sufficientemente chiara e pulita dal punto di vista del codice che la compone - è controllare che essa contenga soltanto un minimo quantitativo di codice PHP, in modo tale che sia facilmente comprensibile ad un designer HTML - che non abbia conoscenza del linguaggio PHP. +è controllare che essa contenga soltanto un minimo quantitativo di codice PHP, in modo tale che sia facilmente comprensibile a un designer HTML +che non abbia conoscenza del linguaggio PHP. Le espressioni PHP più comuni presenti nelle vista sono `echo`, `if/endif`, `foreach/endforeach`. Inoltre non dovrebbe esserci codice PHP che stampi codice HTML. @@ -197,7 +197,7 @@ Listato 2-4 - Il modello, in `model.php` return $posts; } -Il controllore rivisto e riscritto e' mostrato nel Listato 2-5 +Il controllore rivisto e riscritto è mostrato nel Listato 2-5 Listato 2-5,- Il controllore, rivisto, in `index.php` @@ -213,10 +213,10 @@ Listato 2-5,- Il controllore, rivisto, in `index.php` // Richeista della vista require('view.php'); -In questo modo diventa piu semplice leggere il codice del controllore. +In questo modo diventa più semplice leggere il codice del controllore. Il suo unico scopo è quello di ottenere i dati dal modello e passarli alla vista. In un'applicazione più complessa, il controllore controlla anche con la richiesta, la sessione utente, l'autenticazione, e così via. -L'utilizzo di nomi espliciti per le funzioni del modello rende adirittura non necessario l'utilizzo dei commenti +L'utilizzo di nomi espliciti per le funzioni del modello rende addirittura non necessario l'utilizzo dei commenti nel controllore. Lo script del modello è dedito all'accesso dei dati e può essere organizzato di conseguenza. @@ -232,7 +232,7 @@ La logica che gestisce i dati appartiene al modello, la gestione del codice di p L'utilizzo di altri pattern di design possono rendere ancora più semplice l'esperienza di sviluppo e scrittura del codice dell'applicativo. I livelli modello, vista e controllore possono al loro volta essere suddivisi. -### Astrazione del Database +### Astrazione del database Il livello del modello può essere suddiviso a sua volta in un livello di accesso ai dati e un livello di astrazione del database. In questo modo, le funzioni di accesso ai dati non utilizzeranno query dipendenti dal tipo di database scelto, @@ -300,20 +300,20 @@ che richiedano accesso al database. >**NOTE** >Gli esempi mostrati nei Listati 2-6 e 2-7 non risultano ancora del tutto soddisfacenti in quanto ci sarebbe ancora del codice da scrivere ->per poter ottenere una completa e reale astrazione del database (astrazione del codice SQL attravero un costruttore di query, -> spostamento di tutte le funzioni in una classe, e cos via). Ma lo scopo di questa guida non e' mostrare come si debba scrivere -> tutto questo codice, e verrà mostrato nel Capitolo 8 come symfony fornisce già elegantemente questa astrazione. +>per poter ottenere una completa e reale astrazione del database (astrazione del codice SQL attraverso un costruttore di query, +> spostamento di tutte le funzioni in una classe, e così via). Ma lo scopo di questa guida non è mostrare come si debba scrivere +> tutto questo codice, e verrà mostrato nel capitolo 8 come symfony fornisce già elegantemente questa astrazione. ### Elementi della Vista Il livello della vista può beneficiare a sua volta di una separazione interna del codice. -Una pagina web contiene spesso degli elementi presenti e consistentia in tutto l'applicativo: gli header della pagina -il layout grafico, il footer, e il menu' di navigazione. In generale soltanto le parti interne della pagina cambiano. -Per questo motivo la vista e' separata in altri due livelli: layout e template. -Il layout e' solitamente globale nell'applicativo o comunque accomuna un gruppo di pagine. +Una pagina web contiene spesso degli elementi coerenti in tutto l'applicativo: gli header della pagina +il layout grafico, il footer e il menù di navigazione. In generale soltanto le parti interne della pagina cambiano. +Per questo motivo la vista è separata in altri due livelli: layout e template. +Il layout è solitamente globale nell'applicativo o comunque accomuna un gruppo di pagine. Il template si occupa di mostrare i valori delle variabili messe a disposizione dal controllore. -E' necessaria della logica per poter far in modo che queste componenti lavorino insieme, e questa logica di presentazione e' +È necessaria della logica per poter far in modo che queste componenti lavorino insieme, e questa logica di presentazione è gestita appunto dalla vista. In base a questi principi, la parta di vista del Listato 2-3 può essere separate in tre parti, come mostrato dai Listati 2-8, 2-9 e 2-10. @@ -354,37 +354,37 @@ Listato 2-10 - La parte di layout della vista -#### Azioni e Front Controller +#### Azioni e front controller Il controllore mostrato nell'esempio precedente non effettua molte operazioni, ma in una applicazione web reale, esso deve svolgere molti compiti. Un compito importante e comune a tutti i controllori dell'applicativo. -Un compito comune include la gestione della request, sicurezza, caricamento delle configurazuone e faccende simili. +Un compito comune include la gestione della richiesta, sicurezza, caricamento delle configurazione e faccende simili. Questo è il motivo per cui spesso il controllore è suddiviso in un front controller, che è unico in tutto l'applicativo, e azioni che contengono solamente il codice del controllore specifico di una pagina. Uno dei grandi vantaggi nell'avere un front controller è che viene offerto un unico punto di accesso per tutto l'applicativo. -Qualora si decidesse di rendere inacessibile l'applicativo, basterà semplicemente modificare lo script del front controller. +Qualora si decidesse di rendere inaccessibile l'applicativo, basterà semplicemente modificare lo script del front controller. In un'applicativo sprovvisto di front controller, si dovrebbe intervenire su ogni singolo controllore per poter ottenere lo stesso effetto. -#### Orientamento agli Oggetti +#### Orientamento agli oggetti Tutti gli esempi mostrati in precedenza sono stati scritti con un paradigma di programmazione procedurale. Le possibilità offerte dalla OOP dei moderni linguaggi di programmazione rende la programmazione stessa più semplice, dato che gli oggetti incapsulano logica, ereditano uno dall'altro e forniscono un chiaro e pulito utilizzo dei nomi. -Implementare un'architettura MVC con un linguaggio che non sia object-oriented produrrebbe problematiche nella gestione dei namespace, duplicazione del codice +Implementare un'architettura MVC con un linguaggio che non sia orientato agli oggetti produrrebbe problematiche nella gestione dei namespace, duplicazione del codice e supratutto un codice difficile da leggere. Lo sviluppo orientato agli oggetti permette agli sviluppatori di utilizzare strumenti e componenti come l'oggetto vista, l'oggetto controllore le classi di modello e trasformare tutte le funzioni degli esempi precedenti in metodi. -E' una necessita' per un'architettura MVC. +È una necessità per un'architettura MVC. >**TIP** > Se si volesse approfondire meglio i vari design pattern per un applicativo web in un contesto object-oriented > si consiglia la lettura di Patterns of Enterprise Application Architecture by Martin Fowler (Addison-Wesley, ISBN: 0-32112-742-0). ->Il codice d'esempio presente nel libro di Fowler e' scritto in Java o C#, ma e' piuttosto comprensibile anche ad uno sviluppatore PHP. +>Il codice d'esempio presente nel libro di Fowler è scritto in Java o C#, ma è piuttosto comprensibile anche a uno sviluppatore PHP. ### Implementazione del pattern MVC di symfony @@ -412,30 +412,30 @@ Sette script, diversi file da aprire e modificare ogni volta che si crea una pag Ciò nonostante symfony rende le cose semplici. Symfony implementa il meglio dell'architettura MVC in modo da rendere veloce e indolore lo sviluppo di una applicazione. -Per prima cosa, il Front Controlle e il layout sono gli stessi per tutte le azioni dell'applicativo. +Per prima cosa, il Front Controller e il layout sono gli stessi per tutte le azioni dell'applicativo. È possibile avere controllori e layout multipli, ma è necessario solo uno di essi. -Il Front controller e' un componente puramente in logica MVC e non ci sarà mai l'esigenza di scriverne uno perche' +Il Front controller è un componente puramente in logica MVC e non ci sarà mai l'esigenza di scriverne uno perché symfony si preoccuperà di generarlo. L'altra buona notizia è che le classi del modello sono anch'esse generate automaticamente, -basandosi sulla struttura dei dati. Questo compito di autogenerazione delle classi del modello è affidato alla libreria ORM, che fornisce lo scheletro e la generazione del codice. +basandosi sulla struttura dei dati. Questo compito di auto-generazione delle classi del modello è affidato alla libreria ORM, che fornisce lo scheletro e la generazione del codice. Se la libreria ORM trovasse una chiave esterna o un campo data, genererà degli speciali metodi che renderanno estremamente semplice la manipolazione dei dati e le relazioni tra essi. -La parte di astrazione del database è totalmente invisibile perché viene gestita nativamente da PHP Data Objects. -Qualora si decidesse di cambiare il motore del database, non si dovra' toccare minimamente una singola riga di codice applicativo. +La parte di astrazione del database è totalmente invisibile perché viene gestita nativamente da oggetti PHP. +Qualora si decidesse di cambiare il motore del database, non si dovrà toccare minimamente una singola riga di codice applicativo. Occorre solamente cambiare un parametro di configurazione. Inoltre la logica della vista può essere descritta attraverso un semplice file di configurazione, senza che ci sia la necessità -di scrivere dell codice applicativo. +di scrivere del codice applicativo. -Figura 2-2 - Symfony workflow +Figura 2-2 - Flusso di lavoro di symfony -![Symfony workflow](http://www.symfony-project.org/images/book/1_4/F0202.png "Symfony workflow") +![Flusso di lavoro di symfony](http://www.symfony-project.org/images/book/1_4/F0202.png "Flusso di lavoro di symfony") Questo significa che per quanto riguarda la lista dei post descritta in precedenza saranno necessari solamente tre file come mostrato nei Listati 2-11, 2-12, e 2-13. -Listato 2-11 - `list` Action, in `myproject/apps/myapp/modules/weblog/actions/actions.class.php` +Listato 2-11 - Azione `list`, in `myproject/apps/myapp/modules/weblog/actions/actions.class.php` [php] @@ -464,7 +464,7 @@ Listato 2-12 - `list` Template, in `myproject/apps/myapp/modules/weblog/template -Si dovrà definira un layout, come mostrato nel Listato 2-13, ma esso sarà riutilizzato diverse volte. +Si dovrà definire un layout, come mostrato nel Listato 2-13, ma esso sarà riutilizzato diverse volte. Listato 2-13 - Layout, in `myproject/apps/myapp/templates/layout.php` @@ -491,12 +491,12 @@ di gestione degli URL, ambienti multipli e tanti altri strumenti di sviluppo. L'implementazione MVC in symfony utilizza diverse classi che verranno spesso citate all'interno di questa guida: - * `sfController` è la classe controllore. Decodifica la request e la inoltra alla action. - * `sfRequest` immagazzina tutti gli elementi della request (parametri, cookies, headers e così via). - * `sfResponse` contiente gli header e il contenuto della response. Questo è l'oggetto che sarà eventualmente convertito in una response HTML e che a sua volta sarà inviata all'utente. + * `sfController` è la classe controllore. Decodifica la richiesta e la inoltra all'azione. + * `sfRequest` immagazzina tutti gli elementi della richiesta (parametri, cookies, headers e così via). + * `sfResponse` contiente gli header e il contenuto della risposta. Questo è l'oggetto che sarà eventualmente convertito in una risposta HTML e che a sua volta sarà inviata all'utente. * Il contesto (ottenuto invocando `sfContext::getInstance()`) mantiene una referenza a tutti gli oggetti principali e alla configurazione corrente; è accessibile in ogni punto dell'applicativo. -Nel capitolo 6 questi oggetti verrano approfonditi maggiormente. +Nel capitolo 6 questi oggetti verranno approfonditi maggiormente. Come si può notare, tutte le classi fornite da symfony utilizzano il prefisso 'sf', così come le variabili del nocciolo nei template. Questo serve a scongiurare problematiche relative all'utilizzo di nomi per variabili e classi utilizzate dallo sviluppatore e rendendo semplice il loro riconoscimento. @@ -506,11 +506,11 @@ Questo serve a scongiurare problematiche relative all'utilizzo di nomi per varia >Ci sono due eccezioni: le classi del nocciolo iniziano con `sf`, in minuscolo, e le variabili nei template utilizzano >il trattino basso come separatore. -Organizzazione del Codice ------------------ +Organizzazione del codice +------------------------- -Dopo aver illustrato i diversi componenti di un'applicazione symofony, mostraimo come essi sono sono organizzati. -Symfony organizza il codice in una struttura di progetto e colloca i file in una struttura standar ad albero. +Dopo aver illustrato i diversi componenti di un'applicazione symofony, mostriamo come essi sono sono organizzati. +Symfony organizza il codice in una struttura di progetto e colloca i file in una struttura standard ad albero. ### Struttura di Progetto, Applicazioni, Moduli e Azioni @@ -518,7 +518,7 @@ In symfony, un progetto è un insieme di servizi e operazioni disponibili sotto condividendo lo stesso modello. All'interno di un progetto, le operazioni sono raggruppate in modo logico all'interno delle applicazioni. -Un'applicazione può normalemnte girare indipendentemente dalle altre applicazioni dello stesso progetto. +Un'applicazione può normalmente girare indipendentemente dalle altre applicazioni dello stesso progetto. Nella maggior parte dei casi, un progetto conterrà due applicazioni: una per il front-office e un per il back-office. condividendo lo stesso database. Ma è possibile avere anche un progetto contenente dei mini-siti, un'applicazione per ogni sito. Da notare che i link tra le applicazioni devono essere in forma assoluta. @@ -530,42 +530,42 @@ Ad esempio si potrebbe avere dei moduli `home`, `articoli`, `help`, `carrelloDel I moduli contengono le azioni, le quali rappresentano le varie azioni che possono essere eseguite all'interno di un modulo. Per esempio, un modulo nominato `carrelloDellaSpesa` può contenere le azioni `aggiungi`, `mostra` e aggiorna. Aver a che fare con le azioni è quasi come interagire con le pagine di una classica applicazione web, sebbene due azioni -possano risultare nella stessa pagina (ad esempio, aggiungendo un commento ad un post in un weblog comporterà la rivisualizzazione del post con il nuovo commento). +possano risultare nella stessa pagina (ad esempio, aggiungendo un commento a un post in un blog comporterà la ri-visualizzazione del post con il nuovo commento). >**TIP** >Se ci fossero troppi livelli di moduli e azioni per un progetto iniziale, è possibile raggruppare tutte le azioni in un singolo modulo, ->in modo tale che la stuttura si mantenga semplice. Nel caso in cui successivamente l'applicazione diventi più complessa, +>in modo tale che la struttura si mantenga semplice. Nel caso in cui successivamente l'applicazione diventi più complessa, >sarà necessario disporre le azioni in moduli separati. ->Come descritto nel Capitolo 1, l'operazione di riscrivere il codice per migliorare la struttura e la leggibilità dello stesso (ma preservando il suo comportamento) ->viene comunemente chiamato `refactoring`, e questo viene fatto frequentemente applicando i principi RAD. +>Come descritto nel capitolo 1, l'operazione di riscrivere il codice per migliorare la struttura e la leggibilità dello stesso (ma preservando il suo comportamento) +>viene comunemente chiamato 'rifattorizzazione' e questo viene fatto frequentemente applicando i principi RAD. -La Figura 2-3 mostra un esempio di codice per un progetto di un weblog, in una struttura project/application/module/action. +La Figura 2-3 mostra un esempio di codice per un progetto di un blog, in una struttura `project/application/module/action`. Figura 2-3 - Esempio di organizzazione del codice -![Example of code organization](http://www.symfony-project.org/images/book/1_4/F0203.png "Example of code organization") +![Esempio di organizzazione del codice](http://www.symfony-project.org/images/book/1_4/F0203.png "Esempio di organizzazione del codice") -### Strutture ad Albero dei File +### Strutture ad albero dei file -Tutti i progetti web condividono lo stesso tipo di contenuti, as esempio: +Tutti i progetti web condividono lo stesso tipo di contenuti, ad esempio: * Un database, come MYSQL o PostgreSQL - * File statici (HTML, immagini, file Javascript, fogli di stile e così via) + * File statici (HTML, immagini, file JavaScript, fogli di stile e così via) * File caricati dagli utenti del sito e gli amministratori * Classi e librerie PHP * Librerie esterne (script di terze parti) - * File Batch (scipt che vengono lanciati da linea di comando o via cron) + * File Batch (script che vengono lanciati da linea di comando o via cron) * File di Log (informazioni scritte dall'applicativo e/o dal server) * File di configurazione Symfony fornisce una struttura di file standard per organizzare tutti questi contenuti in modo logico e consistente con le scelte architetturali (MVC pattern e raggruppamento progetto/applicazione/modulo). Questa è la struttura che viene creata quando si inizializza un progetto, applicazione o modulo. -Ovviamente è possibile personalizzare completamente la struttura dei file e delle directory qualora fosse necessario. +Ovviamente è possibile personalizzare completamente la struttura dei file e delle cartelle, qualora fosse necessario. #### Struttura principale dell'albero -Queste sono le directory alla base di un progetto symfony: +Queste sono le cartelle alla base di un progetto symfony: apps/ frontend/ @@ -589,25 +589,24 @@ Queste sono le directory alla base di un progetto symfony: js/ uploads/ -Tabella 2-1 descrive il contenuto delle directory mostrate +Tabella 2-1 descrive il contenuto delle cartelle mostrate -Tabella 2-1 - Directory di base +Tabella 2-1 - Cartelle di base -Directory | Description ----------- | ------------ -`apps/` | Contiene una directory per ogni applicazione del progetto (tipicamente, `frontend` and `backend` pre il front e back office). -`cache/` | Contiene la versione cache della configurazione, e (se attivata) la versione cache delle azioni e dei template del progetto. Il meccanismo di caching (descitto nel capitolo 12) utilizza questi file per velocizzare i tempi di risposta dell'applicativo. Ciascuna applicazione avrà una subdirectory, contenente file PHP preprocessati e file HTML. -`config/` | Holds the general configuration of the project. +Cartella | Descrizione +---------- | ----------- +`apps/` | Contiene una cartella per ogni applicazione del progetto (tipicamente, `frontend` e `backend`). +`cache/` | Contiene la versione cache della configurazione, e (se attivata) la versione cache delle azioni e dei template del progetto. Il meccanismo di cache (descritto nel capitolo 12) utilizza questi file per velocizzare i tempi di risposta dell'applicativo. Ciascuna applicazione avrà una sotto-cartella, contenente file PHP pre-processati e file HTML. `config/` | Contiene la configurazione generale del progetto. `data/` | Contiene i file dati del progetto come lo schema del database, un file SQL per la creazione delle tabelle o anche un file SQLite. `doc/` | Contiene la documentazione del progetto -`lib/` | Contiene classi esterne o librerie. In essa può essere aggiunto del codice che deve essere condiviso tra le applicazioni. La subdirectory `model/` contiene gli oggetti del modello del progetto (descritto nel Capitolo 8). -`log/` | Contiene i file di log generati direttamente da symfony. Possono anche essere presenti i file di log del webserver, del database o file di log provenienti da qualsiasi punto del progetto. Symfony crea un file di log per ogno applicazioni e ambiente (i file di log verranno discussi nel Capitolo 16). -`plugins/` | Contiene i vari plugin installati nell'applicativo (i plugin verranno discussi nel Capitolo 17). -`test/` | Contiene test unitari e funzionali scritti in PHP e compatibili con il framework di test di symfony (discusso nel Capitolo 15). Durante il setup de progetto, symfony crea automaticamente dei file con dei test basilari. -`web/` | È la directory root per il webserver. Essa contieni gli unici file accessibili dall'esterno. +`lib/` | Contiene classi esterne o librerie. In essa può essere aggiunto del codice che deve essere condiviso tra le applicazioni. La sotto-cartella `model/` contiene gli oggetti del modello del progetto (descritto nel capitolo 8). +`log/` | Contiene i file di log generati direttamente da symfony. Possono anche essere presenti i file di log del webserver, del database o file di log provenienti da qualsiasi punto del progetto. Symfony crea un file di log per ogni applicazione e ambiente (i file di log verranno discussi nel capitolo 16). +`plugins/` | Contiene i vari plugin installati nell'applicativo (i plugin verranno discussi nel capitolo 17). +`test/` | Contiene test unitari e funzionali scritti in PHP e compatibili con il framework di test di symfony (discusso nel capitolo 15). Durante il setup del progetto, symfony crea automaticamente dei file con dei test basilari. +`web/` | È la cartella radice del server web. Essa contiene gli unici file accessibili dall'esterno. -#### Struttura ad Albero di un'Applicazione +#### Struttura ad albero di un'applicazione La struttura ad albero di un'applicazione è la stessa: @@ -620,20 +619,20 @@ La struttura ad albero di un'applicazione è la stessa: templates/ layout.php -Tabella 2-2 descrive le subdirectory dell'applicazione +Tabella 2-2 descrive le sotto-cartelle dell'applicazione -Tabella 2-2 - Subdirectory dell'applicazione +Tabella 2-2 - Sotto-cartelle dell'applicazione -Directory | Description +Cartella | Descrizione ------------ | ----------- -`config/` | Contiene un insieme di file di configurazione YAML. In questa subdirectory sono contenuti i principali di configurazione, escludendo i parametri iniziali definiti nel framework stesso. Se fosse necessario i valori dei parametri iniziali posso essere comunque sovrascritti. Questo argomento verra' trattato nello specifico nel Capitolo 5. -`i18n/` | Contiene i file utilizzati per l'intenazionalizzazione dell'applicativo (il Capitolo 13 approfondisce l'argomento). E' possibile non tenere conto di questa directory qualora si utilizzasse un database per l'internazionalizzazione. +`config/` | Contiene un insieme di file di configurazione YAML. In questa sotto-cartelle sono contenuti i principali di configurazione, escludendo i parametri iniziali definiti nel framework stesso. Se fosse necessario i valori dei parametri iniziali posso essere comunque sovrascritti. Questo argomento verrà trattato nello specifico nel capitolo 5. +`i18n/` | Contiene i file utilizzati per l'internazionalizzazione dell'applicativo (il capitolo 13 approfondisce l'argomento). È possibile non tenere conto di questa cartella qualora si utilizzasse un database per l'internazionalizzazione. `lib/` | Contiene classi e librerie specifiche all'applicazione. `modules/` | Contiene tutti i moduli dell'applicazione `templates/` | Contiene i template globali dell'applicazione, condivisi da tutti i moduli. Contiene il file `layout.php` come predefinito, che rappresenta il layout principale nel quale i template dei moduli vengono inseriti. >**NOTE** ->Le directory `i18n/`, `lib/` e `modules/` sono vuote quando viene creata una nuova applicazione. +>Le cartelle `i18n/`, `lib/` e `modules/` sono vuote quando viene creata una nuova applicazione. Le classi di un'applicazione non possono accedere a metodi o attributi di altre applicazioni dello stesso progetto. Da notare che i link tra le diverse applicazioni devono essere in forma assoluta e quindi è da tener ben presente qualora si decidesse di suddividere un progetto in diverse applicazioni. @@ -642,7 +641,7 @@ Da notare che i link tra le diverse applicazioni devono essere in forma assoluta #### Struttura ad albero di un modulo Ogni applicazione contiene uno o più moduli. -Ogni modulo ha le sue subdirectory nella direcotory `modules`, e il nome di tale directory viene scelta durante il setup. +Ogni modulo ha le sue sotto-cartelle nella cartella `modules` e il nome di tale cartella viene scelta durante la configurazione. Tipica struttura ad albero di un modulo: @@ -657,25 +656,25 @@ Tipica struttura ad albero di un modulo: templates/ indexSuccess.php -Tabella 2-3 descrive le subdirectory di un modulo. +Tabella 2-3 descrive le sotto-cartelle di un modulo. -Tabella 2-3 - Subdirectory di un modulo +Tabella 2-3 - Sotto-cartelle di un modulo -Directory | Description ------------- | ------------ -`actions/` | Contiene generalmente un singolo file chiamato `actions.class.php`, nel quale sono scritte tutte le azione del modulo stesso. E' possibile scrivere azioni diverse di un modulo in file separati. +Cartella | Descrizione +------------ | ----------- +`actions/` | Contiene generalmente un singolo file chiamato `actions.class.php`, nel quale sono scritte tutte le azioni del modulo stesso. È possibile scrivere azioni diverse di un modulo in file separati. `config/` | Contiene file di configurazione personalizzati con parametri locali per il modulo. `lib/` | Contiene classi e librerie specifiche del modulo. `templates/` | Contiene i template corrispondenti all'azione del modulo. Un template predefinito, chiamato `indexSuccess.php`, viene creato durante il setup del modulo. >**NOTE** ->Le directory `config/` e `lib/` non vengono create automaticamente per un nuovo modulo, devono essere create manualmente qualora fossero necessarie. +>Le cartelle `config/` e `lib/` non vengono create automaticamente per un nuovo modulo, devono essere create manualmente qualora fossero necessarie. -#### Struttura ad albero della directory Web +#### Struttura ad albero della cartella Web -Esistono pochi vincoli per la directory `web`, essa è la directory contenente file accessibili pubblicamente dall'esterno. -Seguendo poche regole base sarà possibile ottenere dei comportamenti predefiniti, messi a diposizione dal framework stesso, e utili scorciatoie da utilizzare all'interno dei template. -Esempio della struttura della directory `web`: +Esistono pochi vincoli per la cartella `web`, essa è la cartella contenente file accessibili pubblicamente dall'esterno. +Seguendo poche regole base sarà possibile ottenere dei comportamenti predefiniti, messi a disposizione dal framework stesso, e utili scorciatoie da utilizzare all'interno dei template. +Esempio della struttura della cartella `web`: web/ css/ @@ -683,30 +682,30 @@ Esempio della struttura della directory `web`: js/ uploads/ -È convenzione che i file statici vengano collocati nell directory mostrate nella Tabella 2-4 +È convenzione che i file statici vengano collocati nella cartella mostrate nella Tabella 2-4 -Tabella 2-4 Sottodirectory tipiche della directory Web +Tabella 2-4 Sotto cartella tipiche della cartella Web -Directory | Description +Cartella | Descrizione ---------- | ----------- `css/` | Contiene fogli di stile con estensione `.css`. `images/` | Contiene immagini con estensione `.jpg`, `.png`, o `.gif`. -`js/` | Contiene file Javascript con estensione `.js`. -`uploads/` | Contiene file caricati dagli utenti. Sebbene la directory contenga solitamente immagini, è separata dalla directory delle immagini in modo che la sincronizzazione dei server di sviluppo e server di produzione non interferisca con le immagini caricate. +`js/` | Contiene file JavaScript con estensione `.js`. +`uploads/` | Contiene file caricati dagli utenti. Sebbene la cartella contenga solitamente immagini, è separata dalla cartella delle immagini in modo che la sincronizzazione dei server di sviluppo e server di produzione non interferisca con le immagini caricate. >**NOTE** >Sebbene sia altamente consigliato che venga mantenuta la struttura ad albero predefinita, è possibile modificarla ->per esigenze specifiche, ad esempio per permettere ad un progetto di girare su un server con strutture particolari. ->Per maggiori informazioni su quest'ultimo argomento è necessario riferirsi al Capitolo 19 nel quale verrà mostrato come modificare la struttura ad albero dei file. +>per esigenze specifiche, ad esempio per permettere a un progetto di girare su un server con strutture particolari. +>Per maggiori informazioni su quest'ultimo argomento è necessario riferirsi al capitolo 19 nel quale verrà mostrato come modificare la struttura ad albero dei file. -Strumenti Comuni ------------------- +Strumenti comuni +---------------- Durante la lettura di questa guida e nello sviluppo di progetti con symfony si incontreranno alcune tecniche utilizzate ripetutamente. Tra queste ci sono: contenitori dei parametri, costanti e caricamento automatico delle classi. -### Contentori di Parametri +### Contenitori di parametri Molte delle classi che compongono il framework symfony sono dei contenitori di parametri. È un modo conveniente di incapsulare gli attributi con dei metodi getter e setter chiari e puliti. @@ -732,13 +731,13 @@ Listato 2-15 - Utilizzo del metodo proxy del contenitore dei parametri dell'ogge => 'bar' Il metodo getter del contenitore di parametri accetta un valore predefinito come secondo argomento. -Tutto ciò fornisce un utile meccanismo di fallback che risulta molto più consico rispetto ad un blocco condizionale. +Tutto ciò fornisce un utile meccanismo di fallback che risulta molto più conciso rispetto a un blocco condizionale. Si veda come esempio il Listato 2-16. Listato 2-16 - Utilizzo del valore predefinito [php] - // Il parametro 'foobar' non è definito, il metodo getter ritorna un valore nullo + // Il parametro 'foobar' non è definito, il metodo getter restituisce un valore nullo echo $request->getParameter('foobar'); => null @@ -773,7 +772,7 @@ Listato 2-17 - Utilizzo dei namespace con il contenitore dei parametri di `sfUse È possibile aggiungere un contenitore dei parametri a delle classi personalizzate per trarre vantaggio da questo meccanismo -Listato 2-18 - Aggiungere un contenitore dei parametri ad una classe +Listato 2-18 - Aggiungere un contenitore dei parametri a una classe [php] class MyClass @@ -815,33 +814,33 @@ Il capitolo 5 illustra i metodi di `sfConfig` nel dettaglio. ### Caricamento automatico delle classi Solitamente in PHP quando viene invocato un metodo di una classe o viene creato un oggetto c'è la necessità di includere per prima cosa -la definizione di tale clasee: +la definizione di tale classe: [php] include_once 'classes/MyClass.php'; $myObject = new MyClass(); -In un progetto di grosse dimensione con molte classi e una profonda e articolata struttura di directory, tener traccia di tutti i file delle vari classi e i percorsi delle stesse può diventare una perdita di tempo. -Symfony fornisce una funzione `spl_autoload_register()` che rende sueprfluo l'utilizzo della direttiva `include_once`, e che permette di scrivere direttamente: +In un progetto di grosse dimensione con molte classi e una profonda e articolata struttura di cartelle, tener traccia di tutti i file delle vari classi e i percorsi delle stesse può diventare una perdita di tempo. +Symfony fornisce una funzione `spl_autoload_register()` che rende superfluo l'utilizzo della direttiva `include_once`, e che permette di scrivere direttamente: [php] $myObject = new MyClass(); -Symfony cercherà all'interno delle directory `lib/' la definizione della classe `MyClass` in tutti file che termineranno con `class.php`. +Symfony cercherà all'interno delle cartelle `lib/' la definizione della classe `MyClass` in tutti file che termineranno con `class.php`. Se la classe verrà trovata, verrà inclusa automaticamente. -Collocando le proprie classi all'interno delle directory `lib/' non sarà più necessario includerle. +Collocando le proprie classi all'interno delle cartelle `lib/' non sarà più necessario includerle. Questo è il motivo per il quale solitamente i progetti symfony non contengono direttive `include_once` o `require_once`. Sommario -------- +-------- -L'utilizzo di un framework MVC obbliga lo sviluppatore ad organizzare il codice in accordo con le convenzioni del framework stesso. -Il codice di presentazione appartiene alla vista, la manipolazione dei dati appartiene al modello, e la logica della request appartiene al controllore. +L'utilizzo di un framework MVC obbliga lo sviluppatore a organizzare il codice in accordo con le convenzioni del framework stesso. +Il codice di presentazione appartiene alla vista, la manipolazione dei dati appartiene al modello, e la logica della richiesta appartiene al controllore. Symfony è un framework MVC scritto in PHP. La sua struttura permette di ottenere il meglio grazie all'utilizzo del pattern MVC, mantenendo al contempo una praticità e semplicità d'utilizzo. Grazie alla sua versatilità e configurabilità, symfony è adatto per tutte le tipologie di applicativi web. -Ora che è stata mostrata la teoria alla base di symfony si è in grado di sviluppare una prima applicazione, ma prima di questo occorre un'installazione di symf ony e un -server di sviluppo. \ No newline at end of file +Ora che è stata mostrata la teoria alla base di symfony, si è in grado di sviluppare una prima applicazione, ma prima di questo occorre un'installazione di symfony e un +server di sviluppo. diff --git a/gentle-introduction/it/04-The-Basics-of-Page-Creation.markdown b/gentle-introduction/it/04-The-Basics-of-Page-Creation.markdown index 47a30af..1a5d688 100644 --- a/gentle-introduction/it/04-The-Basics-of-Page-Creation.markdown +++ b/gentle-introduction/it/04-The-Basics-of-Page-Creation.markdown @@ -24,7 +24,7 @@ La riga di comando di symfony automatizza la creazione di moduli. Basta eseguire >> tokens ~/mioprogetto/apps/frontend/modules/contenuto/actions/actions.class.php >> tokens ~/mioprogetto/apps/frontend/modules/contenuto/templates/indexSuccess.php -A parte le cartelle `actions/` e `templates/`, questo comando crea solo tre file. Il primo si trova nella cartella `test/`, riguarda i test funzionali e non si ha bisogno di farci caso fino al Capitolo 15. `actions.class.php` (mostrato nel Listato 4-1) esegue il forward al modulo predefinito con la pagina di congratulazioni. Il file `templates/indexSuccess.php` è vuoto. +A parte le cartelle `actions/` e `templates/`, questo comando crea solo tre file. Il primo si trova nella cartella `test/`, riguarda i test funzionali e non si ha bisogno di farci caso fino al capitolo 15. `actions.class.php` (mostrato nel Listato 4-1) esegue il forward al modulo predefinito con la pagina di congratulazioni. Il file `templates/indexSuccess.php` è vuoto. Listato 4-1 - L'azione predefinita generata in `actions/actions.class.php` @@ -104,7 +104,7 @@ symfony si lamenterà per il fatto che manca il template `showSuccess.php`. È n > > http://localhost/articles/tagged/finance+france+euro > ->Symfony sa come fare il parse e generare URL intelligenti per l'utente. Il sistema per le rotte estrapola automaticamente i parametri della richiesta da una URL intelligente e li rende disponibili all'azione. Formatta anche i link inclusi nella risposta in modo che vengano mostrati in modo "intelligente". Per saperne di più su questa caratteristica, leggere il Capitolo 9. +>Symfony sa come fare il parse e generare URL intelligenti per l'utente. Il sistema per le rotte estrapola automaticamente i parametri della richiesta da una URL intelligente e li rende disponibili all'azione. Formatta anche i link inclusi nella risposta in modo che vengano mostrati in modo "intelligente". Per saperne di più su questa caratteristica, leggere il capitolo 9. > >Nel complesso, questo significa che il modo in cui si dà un nome alle azioni delle applicazioni non dovrebbe essere influenzato dal modo in cui scegliamo l'URL per chiamarli, ma dalle funzioni delle azioni nell'applicazione. Il nome di una azione deve descrivere cosa fa l'azione reale e spesso è spesso un verbo in forma all'infinito (come `show`, `list`, `edit` e così via). I nomi delle azioni possono essere del tutto invisibili all'utente finale, quindi non bisogna aver paura di utilizzare nomi di azioni espliciti (come `listByName` or `showWithComments`). In questo modo si può risparmiare sui commenti del codice atti a spiegare la funzione dell'azione e inoltre il codice sarà molto più facile da leggere. @@ -208,7 +208,7 @@ Listato 4-9 - Gli helper `link_to()` e `url_for()` L'HTML risultante sarà lo stesso del precedente, eccetto che quando si cambiano le regole delle rotte, tutti i template si comporteranno correttamente e riformatteranno gli URL di conseguenza. -L'utilizzo dei form merita un capitolo a sé stante, dato che symfony fornisce molti strumenti per renderli ancora più facili. Si imparerà di più su questi helper nel Capitolo 10. +L'utilizzo dei form merita un capitolo a sé stante, dato che symfony fornisce molti strumenti per renderli ancora più facili. Si imparerà di più su questi helper nel capitolo 10. L'helper `link_to()`, così come altri helper, accetta un altro parametro per opzioni speciali e addizionali attributi per i tag. Il Listato 4-10 mostra un esempio di opzioni passate come parametro e dell'HTML risultante. Le opzioni possono essere sia un array associativo che una semplice stringa con coppie `chiave=valore` separate da spazi. @@ -237,7 +237,7 @@ Ogni volta che si utilizza un helper di symfony che genera un tag HTML, è possi >**NOTE** >Essendo necessaria una ulteriore analisi e trasformazione, la sintassi con stringa è un po' più lenta della sintassi con gli array. -Come tutti gli helper di symfony, gli helper per i link sono numerosi e hanno molte opzioni. Il Capitolo 9 li descrive in dettaglio. +Come tutti gli helper di symfony, gli helper per i link sono numerosi e hanno molte opzioni. Il capitolo 9 li descrive in dettaglio. Ottenere informazioni dalla Request ----------------------------------- diff --git a/gentle-introduction/it/05-Configuring-Symfony.markdown b/gentle-introduction/it/05-Configuring-Symfony.markdown index d242ef6..a0069f3 100644 --- a/gentle-introduction/it/05-Configuring-Symfony.markdown +++ b/gentle-introduction/it/05-Configuring-Symfony.markdown @@ -31,7 +31,7 @@ Tenendo conto di questi svantaggi, symfony utilizza file di configurazione solo ### Sintassi YAML e convenzioni di symfony -Per la sua configurazione, symfony utilizza il formato YAML, invece dei più tradizionali INI e XML. YAML mostra la struttura tramite indentazione ed è veloce da scrivere. I vantaggi e le regole di base sono già state mostrate nel Capitolo 1. Comunque, occorre tenere a mente qualche convenzione quando si scrivono file YAML. Questa sezione introduce diverse convenzioni tra le più importanti. Per approfondimenti, visitare il [sito web di YAML](http://www.yaml.org/). +Per la sua configurazione, symfony utilizza il formato YAML, invece dei più tradizionali INI e XML. YAML mostra la struttura tramite indentazione ed è veloce da scrivere. I vantaggi e le regole di base sono già state mostrate nel capitolo 1. Comunque, occorre tenere a mente qualche convenzione quando si scrivono file YAML. Questa sezione introduce diverse convenzioni tra le più importanti. Per approfondimenti, visitare il [sito web di YAML](http://www.yaml.org/). Prima di tutto non sono ammessi caratteri di tabulazione in YAML: occorre usare spazi vuoti. I parser YAML non capiscono le tabulazioni, per cui si devono utilizzare spazi vuoti per l'indentazione (la convenzione in symfony è di due spazi), come mostrato nel Listato 5-1. @@ -162,7 +162,7 @@ Listato 5-10 - Gli header di categoria esistono solo per una questione di leggib > >YAML è solo un'interfaccia per definire impostazioni utilizzate da PHP, per cui le configurazioni YAML finiscono per essere trasformate in PHP. Dopo aver navigato la propria applicazione, se ne può controllare la configurazione in cache (ad esempio in cache/frontend/dev/config/). Si vedranno file PHP corrispondenti alle configurazioni YAML. Altre informazioni sulla cache di configurazione sono disponibili più avanti in questo capitolo. > ->La buona notizia è che se non si vuole usare YAML, si può fare la stessa cosa a mano in PHP o con altri formati (come XML o INI). Nel corso di questo libro, vedremo modi alternativi per definire configurazioni senza YAML e impareremo anche come sostituire il gestore di configurazioni di symfony (nel Capitolo 19). Usati largamente, questi trucchi permetteranno di aggirare i file di configurazione o definire il proprio personale formato di configurazione. +>La buona notizia è che se non si vuole usare YAML, si può fare la stessa cosa a mano in PHP o con altri formati (come XML o INI). Nel corso di questo libro, vedremo modi alternativi per definire configurazioni senza YAML e impareremo anche come sostituire il gestore di configurazioni di symfony (nel capitolo 19). Usati largamente, questi trucchi permetteranno di aggirare i file di configurazione o definire il proprio personale formato di configurazione. ### Aiuto, un file YAML ha ucciso l'applicazione! @@ -203,16 +203,16 @@ Se la propria applicazione smette improvvisamente di funzionare dopo un cambio d Riepilogo sui file di configurazione ------------------------------------ -La configurazione è suddivisa in file, per oggetto. Questi file contengono definizioni di parametri o impostazioni. Alcuni di tali parametri possono essere sovrascritti a diversi livelli (progetto, applicazione e modulo), altri sono specifici di un certo livello. I prossimi capitoli prenderanno in esame le configurazioni relativamente alle loro finalità principali, mentre il Capitolo 19 esaminerà le configurazioni avanzate. +La configurazione è suddivisa in file, per oggetto. Questi file contengono definizioni di parametri o impostazioni. Alcuni di tali parametri possono essere sovrascritti a diversi livelli (progetto, applicazione e modulo), altri sono specifici di un certo livello. I prossimi capitoli prenderanno in esame le configurazioni relativamente alle loro finalità principali, mentre il capitolo 19 esaminerà le configurazioni avanzate. ### Configurazione di progetto Ci sono pochi file di configurazione predefiniti per il progetto. Di seguito quelli che si trovano nella cartella `progetto/config/`: - * `ProjectConfiguration.class.php`: Questo è assolutamente il primo file incluso da ogni richiesta o comando. Contiene i percorsi ai file del framework e può essere cambiato per usare un'installazione diversa. Vedere il Capitolo 19 per usi avanzati di questo file. - * `databases.yml`: Qui è dove si definisce l'accesso e la connessione al database (host, login, password, nome del database e così via). Vedremo di più su questo nel Capitolo 8. Può essere sovrascritto a livello di applicazione. - * `properties.ini`: Questo file gestisce parametri utilizzati a linea di comando, inclusi il nome del progetto e le impostazioni di connessione a server remoti. Vedere il Capitolo 16 per un sommario delle caratteristiche di utilizzo di questo file. - * `rsync_exclude.txt`: Questo file specifica quali cartelle e file devono essere esclusi dalla sincronizzazione tra server. È discusso nel Capitolo 16. + * `ProjectConfiguration.class.php`: Questo è assolutamente il primo file incluso da ogni richiesta o comando. Contiene i percorsi ai file del framework e può essere cambiato per usare un'installazione diversa. Vedere il capitolo 19 per usi avanzati di questo file. + * `databases.yml`: Qui è dove si definisce l'accesso e la connessione al database (host, login, password, nome del database e così via). Vedremo di più su questo nel capitolo 8. Può essere sovrascritto a livello di applicazione. + * `properties.ini`: Questo file gestisce parametri utilizzati a linea di comando, inclusi il nome del progetto e le impostazioni di connessione a server remoti. Vedere il capitolo 16 per un sommario delle caratteristiche di utilizzo di questo file. + * `rsync_exclude.txt`: Questo file specifica quali cartelle e file devono essere esclusi dalla sincronizzazione tra server. È discusso nel capitolo 16. * `schema.yml`: Si tratta del file di configurazione per l'accesso ai dati usato da Propel e Doctrine (gli ORM di symfony). Esso è usato per far funzionare le librerie dell'ORM con le classi di symfony e i dati del progetto. Il file `schema.yml` contiene una rappresentazione del modello relazionale del progetto. Per Doctrine, il file è in `config/doctrine/`. Questi file sono usati per lo più da componenti esterni o dalla linea di comando o devono essere processati prima che il framework carichi il programma di analisi YAML. Ecco perché alcuni di essi non usano il formato YAML. @@ -239,7 +239,7 @@ Dopo aver definito il nome dell'applicazione (`frontend`), l'ambiente (`prod`) e * `$configuration->getRootDir()`: La cartella radice del progetto (di norma dovrebbe rimanere come è, a meno che non si voglia cambiare la struttura delle cartelle). * `$configuration->getApplication()`: Nome dell'applicazione nel progetto. Necessario per calcolare i percorsi dei file. * `$configuration->getEnvironment()`: Nome dell'ambiente (`prod`, `dev` o qualsiasi altro ambiente specifico creato ad hoc per il progetto). Determinerà quali sono le impostazioni di configurazione da utilizzare. Gli ambienti sono spiegati più avanti in questo capitolo. - * `$configuration->isDebug()`: Attivazione della modalità di debug (vedere il Capitolo 16 per i dettagli). + * `$configuration->isDebug()`: Attivazione della modalità di debug (vedere il capitolo 16 per i dettagli). Se si vuole cambiare uno di questi valori, probabilmente occorrerà di un front controller addizionale. Il prossimo capitolo spiegherà più nel dettaglio i front controller e come crearne di nuovi. @@ -248,12 +248,12 @@ Se si vuole cambiare uno di questi valori, probabilmente occorrerà di un front La configurazione dell'applicazione principale è memorizzata in file che si trovano nella cartella `progetto/apps/frontend/config/`: * `app.yml`: Questo file dovrebbe contenere configurazioni specifiche all'applicazione; ad esempio variabili globali che definiscono business logic, che non hanno bisogno di essere memorizzate nel db. Tasse, costi di spedizione, indirizzi e-mail sono memorizzati spesso in questo file, che di base è vuoto. - * `frontendConfiguration.class.php`: questa classe si occupa del bootstrap dell'applicazione, quindi fa tutte le inizializzazioni di base necessarie all'applicazione per partire. È qui che si può definire una struttura di cartelle particolare, oppure delle costanti specifiche (il Capitolo 19 ne fornirà maggiori dettagli). Estende la classe `ProjectConfiguration`. - * `factories.yml`: symfony definisce le proprie classi per gestire le viste, la richiesta, la risposta, le sessioni e così via. Se invece si vogliono utilizzare le proprie classi personali, questo file è i posto in cui definirle (maggiori informazioni nel Capitolo 17). - * `filters.yml`: I filtri sono porzioni di codice eseguiti per ogni richiesta. Qui è dove definisci quali filtri devono essere processati, e può essere sovrascritto in ogni modulo. Il Capitolo 6 fornisce maggiori dettagli sui filtri. - * `routing.yml`: Le regole di routing, che permettono di trasformare un URL illeggibile in uno più "intelligente", sono definite in questo file. Per nuove applicazioni, esistono poche regole predefinite. Il Capitolo 9 è dedicato ai link e al routing. - * `settings.yml`: Le impostazioni principali di un'applicazione symfony sono definiti in questo file. Qui si specifica se la propria applicazione è internazionalizzata, qual è la lingua di default, il timeout per le richieste e se la cache è attiva o meno. Cambiando una linea di questo file si può "spegnere" la propria applicazione, per poterla aggiornare o manutenere. Le impostazioni più comuni e il loro utilizzo sono approfonditi nel Capitolo 19. - * `view.yml`: La struttura predefinita della vista (nome del layout, fogli di stile e JavaScript da includere di default, content-type di default e così via) è definita in questo file. Il Capitolo 7 approfondirà questo file. Queste impostazioni possono essere sovrascritte in ogni modulo. + * `frontendConfiguration.class.php`: questa classe si occupa del bootstrap dell'applicazione, quindi fa tutte le inizializzazioni di base necessarie all'applicazione per partire. È qui che si può definire una struttura di cartelle particolare, oppure delle costanti specifiche (il capitolo 19 ne fornirà maggiori dettagli). Estende la classe `ProjectConfiguration`. + * `factories.yml`: symfony definisce le proprie classi per gestire le viste, la richiesta, la risposta, le sessioni e così via. Se invece si vogliono utilizzare le proprie classi personali, questo file è i posto in cui definirle (maggiori informazioni nel capitolo 17). + * `filters.yml`: I filtri sono porzioni di codice eseguiti per ogni richiesta. Qui è dove definisci quali filtri devono essere processati, e può essere sovrascritto in ogni modulo. Il capitolo 6 fornisce maggiori dettagli sui filtri. + * `routing.yml`: Le regole di routing, che permettono di trasformare un URL illeggibile in uno più "intelligente", sono definite in questo file. Per nuove applicazioni, esistono poche regole predefinite. Il capitolo 9 è dedicato ai link e al routing. + * `settings.yml`: Le impostazioni principali di un'applicazione symfony sono definiti in questo file. Qui si specifica se la propria applicazione è internazionalizzata, qual è la lingua di default, il timeout per le richieste e se la cache è attiva o meno. Cambiando una linea di questo file si può "spegnere" la propria applicazione, per poterla aggiornare o manutenere. Le impostazioni più comuni e il loro utilizzo sono approfonditi nel capitolo 19. + * `view.yml`: La struttura predefinita della vista (nome del layout, fogli di stile e JavaScript da includere di default, content-type di default e così via) è definita in questo file. Il capitolo 7 approfondirà questo file. Queste impostazioni possono essere sovrascritte in ogni modulo. >**TIP** >Tutti i file di configurazione di symfony sono descritti in dettaglio nella [Guida di riferimento a symfony](http://www.symfony-project.org/reference/1_4/it/). @@ -265,15 +265,15 @@ Applicazioni internazionalizzate possono mostrare le pagine in diverse lingue. Q * `factories.yml` della cartella `config/` dell'applicazione: Questo file definisce il factory i18n e le opzioni generali di traduzione, come ad esempio la cultura predefinita per la traduzione, se le traduzioni sono in un file o nel database e il loro formato. * File di traduzione nella cartella `i18n/` dell'applicazione: Questi sono fondamentalmente dei dizionari, che forniscono la traduzione delle parole utilizzate nelle template dell'applicazione in modo che le pagine mostrino testo tradotto quando un utente cambia la lingua. -Nota che l'attivazione delle feature i18n è impostata nel file `settings.yml`. Approfondimenti a tale proposito nel Capitolo 13. +Nota che l'attivazione delle feature i18n è impostata nel file `settings.yml`. Approfondimenti a tale proposito nel capitolo 13. #### Configurazioni addizionali dell'applicazione Un secondo insieme di file di configurazione è posizionato nella cartella di installazione di symfony in `sfConfig::get('sf_symfony_lib_dir')/config/config/`) e non figura nella cartella di configurazione delle applicazioni. Tali impostazioni raramente hanno bisogno di essere modificate, oppure sono globali a tutti i progetti. Comunque, se si avesse bisogno di modificarle, creare un file vuoto nella cartella `progetto/apps/frontend/config/` e sovrascrivere i parametri da cambiare. Le impostazioni definite nell'applicazione hanno sempre la precedenza rispetto a quelle definite nel framework. Di seguito, i file di configurazione nella cartella `config/` dell'installazione di symfony: - * `autoload.yml`: Questo file contiene le impostazioni della funzione di autoloading. Tale funzione ti esonera dall'includere classi personalizzate se esse si trovano in una cartella specifica. Questa funzione è descritta nel Capitolo 19. - * `core_compile.yml`: Queste sono liste di classi da includere per far partire un'applicazione. Queste classi vengono poi concatenate in un file PHP ottimizzato senza commenti, che velocizzerà l'esecuzione minimizzando le operazioni di accesso (è caricato un solo file invece di quaranta per ogni richiesta). Questo risulta specialmente utile se non utilizzi un acceleratore PHP. Le tecniche di ottimizzazione sono descritte nel Capitolo 18. - * `config_handlers.yml`: Qui si possono aggiungere o modificare i gestori usati per processare ogni file di configurazione. Il Capitolo 19 fornisce maggiori dettagli in merito. + * `autoload.yml`: Questo file contiene le impostazioni della funzione di autoloading. Tale funzione ti esonera dall'includere classi personalizzate se esse si trovano in una cartella specifica. Questa funzione è descritta nel capitolo 19. + * `core_compile.yml`: Queste sono liste di classi da includere per far partire un'applicazione. Queste classi vengono poi concatenate in un file PHP ottimizzato senza commenti, che velocizzerà l'esecuzione minimizzando le operazioni di accesso (è caricato un solo file invece di quaranta per ogni richiesta). Questo risulta specialmente utile se non utilizzi un acceleratore PHP. Le tecniche di ottimizzazione sono descritte nel capitolo 18. + * `config_handlers.yml`: Qui si possono aggiungere o modificare i gestori usati per processare ogni file di configurazione. Il capitolo 19 fornisce maggiori dettagli in merito. ### Configurazione del modulo @@ -281,10 +281,10 @@ Per impostazione predefinita, un modulo non ha una configurazione specifica. Ma, Come si può immaginare, le impostazioni di un modulo devono essere nella cartella `progetto/apps/frontend/modules/mymodule/config/`. I file interessati sono i seguenti: - * `generator.yml`: Per i moduli generati secondo una tabella di database (scaffolding e amministrazione), questo file descrive il modo in cui le righe e campi devono essere visualizzati e quali tipi di interazioni sono proposti all'utente (filtri, ordinamenti, pulsanti e così via). Il Capitolo 14 approfondirà l'argomento. - * `module.yml`: Questo file contiene parametri specifici per un modulo (equivalente a `app.yml`, ma a livello di modulo) e la configurazione dell'azione. Il Capitolo 6 fornisce maggiori dettagli in merito. - * `security.yml`: Questo file permette di impostare restrizioni per le azioni. Qui si può impostare il fatto che una certa pagina sia visibile solo agli utenti registrati, oppure a un sottoinsieme di utenti con permessi speciali. Il Capitolo 6 fornisce maggiori dettagli in merito. - * `view.yml`: Questo file contiene le configurazioni delle viste di una o tutte le azioni di un modulo. Permette di sovrascrivere `view.yml` del livello dell'applicazione ed è descritto nel Capitolo 7. + * `generator.yml`: Per i moduli generati secondo una tabella di database (scaffolding e amministrazione), questo file descrive il modo in cui le righe e campi devono essere visualizzati e quali tipi di interazioni sono proposti all'utente (filtri, ordinamenti, pulsanti e così via). Il capitolo 14 approfondirà l'argomento. + * `module.yml`: Questo file contiene parametri specifici per un modulo (equivalente a `app.yml`, ma a livello di modulo) e la configurazione dell'azione. Il capitolo 6 fornisce maggiori dettagli in merito. + * `security.yml`: Questo file permette di impostare restrizioni per le azioni. Qui si può impostare il fatto che una certa pagina sia visibile solo agli utenti registrati, oppure a un sottoinsieme di utenti con permessi speciali. Il capitolo 6 fornisce maggiori dettagli in merito. + * `view.yml`: Questo file contiene le configurazioni delle viste di una o tutte le azioni di un modulo. Permette di sovrascrivere `view.yml` del livello dell'applicazione ed è descritto nel capitolo 7. La maggior parte dei file di configurazione dei moduli offrono la possibilità di definire parametri per tutte le viste o tutte le azioni di un modulo, oppure per un loro sottoinsieme. @@ -521,7 +521,7 @@ Listato 5-18 - Ciò che symfony produce quando analizza `settings.yml` 'sf_escaping_method' => 'ESC_SPECIALCHARS', )); -Il significato dei parametri del file `settings.yml` è spiegato nel Capitolo 19. +Il significato dei parametri del file `settings.yml` è spiegato nel capitolo 19. ### Impostazioni dell'applicazione personalizzati e `app.yml` @@ -570,7 +570,7 @@ Per sapere se una carta di credito è accettata nell'ambiente corrente, controll >**TIP** >Ogni qualvolta si è tentati di definire una costante o un parametro in uno script, considerare se non possa essere meglio metterlo nel file `app.yml`. È un posto molto conveniente per memorizzare i parametri dell'applicazione. -Quando servono parametri personalizzati e diventa difficile utilizzare la sintassi di `app.yml`, si può definire una propria sintassi personalizzata. In questo caso, si può memorizzare la configurazione in un nuovo file, interpretato da un nuovo gestore. Il Capitolo 19 fornisce maggiori informazioni sui gestori di configurazione. +Quando servono parametri personalizzati e diventa difficile utilizzare la sintassi di `app.yml`, si può definire una propria sintassi personalizzata. In questo caso, si può memorizzare la configurazione in un nuovo file, interpretato da un nuovo gestore. Il capitolo 19 fornisce maggiori informazioni sui gestori di configurazione. Suggerimenti per ottenere di più dai file di configurazione ----------------------------------------------------------- diff --git a/gentle-introduction/it/06-Inside-the-Controller-Layer.markdown b/gentle-introduction/it/06-Inside-the-Controller-Layer.markdown index f86f0c2..2649566 100644 --- a/gentle-introduction/it/06-Inside-the-Controller-Layer.markdown +++ b/gentle-introduction/it/06-Inside-the-Controller-Layer.markdown @@ -203,7 +203,7 @@ Listing 6-7 - Metodi comuni `sfActions` >**SIDEBAR** >Il singleton context > ->Abbiamo già visto, nel front controller, una chiamata a `sfContext::createInstance()`. Nell'azione il metodo `getContext()` ritorna lo stesso singleton. Questo è un oggetto molto utile che contiene una referenza a tutti gli oggetti del core di symfony associati a una richiesta mettendo a disposizione una via di accesso a ognuno di loro: +>Abbiamo già visto, nel front controller, una chiamata a `sfContext::createInstance()`. Nell'azione il metodo `getContext()` restituisce lo stesso singleton. Questo è un oggetto molto utile che contiene un riferimento a tutti gli oggetti del nocciolo di symfony associati a una richiesta, mettendo a disposizione una via di accesso a ognuno di loro: > >`sfController`: L'oggetto controllore (`->getController()`) > @@ -227,7 +227,7 @@ Listing 6-7 - Metodi comuni `sfActions` ### Terminare l'azione -Alla fine dell'esecuzione di un'azione si possono assumere diversi comportamenti. Il valore ritornato dal metodo dell'azione determina come la vista verrà generata. Le costanti della classe `sfView` vengono utilizzate per specificate quale template utilizzare per mostrare il risultato dell'azione. +Alla fine dell'esecuzione di un'azione si possono assumere diversi comportamenti. Il valore restituito dal metodo dell'azione determina come la vista verrà generata. Le costanti della classe `sfView` vengono utilizzate per specificate quale template utilizzare per mostrare il risultato dell'azione. Se esiste una vista predefinita da invocare (questo è il caso più comune), l'azione dovrebbe terminare come segue: @@ -267,9 +267,9 @@ Nel caso in cui non esista una vista da chiamare--per esempio nel caso in cui un [php] return sfView::NONE; -Nessun template verrà eseguito in questo caso. Significa che è possibile aggirare completamente il livello della vista e impostare il codice HTML di risposta direttamente in un'azione. Come mostrato nel listato 6-9, symfony mette a disposizione uno specifico metodo `renderText()` per questo caso. Può essere utile quando si ha bisogno di un'azione estremamente responsiva, come per le interazioni Ajax, che verranno affrontate nel Capitolo 11. +Nessun template verrà eseguito in questo caso. Significa che è possibile aggirare completamente il livello della vista e impostare il codice HTML di risposta direttamente in un'azione. Come mostrato nel listato 6-9, symfony mette a disposizione uno specifico metodo `renderText()` per questo caso. Può essere utile quando si ha bisogno di un'azione estremamente responsiva, come per le interazioni Ajax, che verranno affrontate nel capitolo 11. -Listing 6-9 - Aggirare la vista facendo l'echo della risposta e ritornando `sfView::NONE` +Listing 6-9 - Aggirare la vista facendo l'echo della risposta e restituendo `sfView::NONE` [php] public function executeIndex() @@ -587,7 +587,7 @@ Listing 6-18 - Cambiare server session storage, in `apps/frontend/config/factori db_data_col: sess_data # Name of the column storing the session data db_time_col: sess_time # Name of the column storing the session timestamp -L'impostazione `database` definisce quale connessione al database utilizzare. Symfony userà così `databases.yml` (vedere Capitolo 8) per determinare i parametri di connessione (host, nome database, utente e password). +L'impostazione `database` definisce quale connessione al database utilizzare. Symfony userà così `databases.yml` (vedere capitolo 8) per determinare i parametri di connessione (host, nome database, utente e password). La classi disponibili per il session storage sono `sfCacheSessionStorage`, `sfMySQLSessionStorage`, `sfMySQLiSessionStorage`, `sfPostgreSQLSessionStorage` e `sfPDOSessionStorage`; l'ultima è quella da preferire. Per disabilitare totalmente il session storage si può utilizzaree la classe `sfNoStorage`. @@ -601,7 +601,7 @@ Listing 6-19 - Modificare la durata delle sessioni, in `apps/frontend/config/fac param: timeout: 1800 # Durata delle sessioni in secondi -Per conoscere più a fondo i factory fare riferimento al Capitolo 19. +Per conoscere più a fondo i factory fare riferimento al capitolo 19. Sicurezza delle azioni ---------------------- @@ -727,7 +727,7 @@ Listing 6-24 - Lavorare con le credenziali utenti in un template Come per lo stato di autenticato le credenziali sono spesso assegnate all'utente durante il processo di login. Ecco perché l'oggetto `sfUser` viene spesso esteso per aggiungere i metodi di login e logout in modo da impostare lo stato di sicurezza in un posto centralizzato. >**TIP** ->Tra i plugin di symfony [`sfGuardPlugin`](http://www.symfony-project.org/plugins/sfGuardPlugin) e [`sfDoctrineGuardPlugin`](http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin) estendono la classe della sessione per semplificare login e logout. Fare riferimento al Capitolo 17 per maggiori informazioni. +>Tra i plugin di symfony [`sfGuardPlugin`](http://www.symfony-project.org/plugins/sfGuardPlugin) e [`sfDoctrineGuardPlugin`](http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin) estendono la classe della sessione per semplificare login e logout. Fare riferimento al capitolo 17 per maggiori informazioni. ### Credenziali complesse @@ -961,7 +961,7 @@ Listing 6-33 - Filtro per comunicazione sicura } } -I filtri vengono utilizzati in modo massivo nel plug-in visto che permettono di estendere le funzionalità di un'applicazione in modo completo. Fare riferimento al Capitolo 17 per saperne di più sui plugin. +I filtri vengono utilizzati in modo massivo nel plug-in visto che permettono di estendere le funzionalità di un'applicazione in modo completo. Fare riferimento al capitolo 17 per saperne di più sui plugin. Configurazione dei moduli ------------------------- diff --git a/gentle-introduction/it/07-Inside-the-View-Layer.markdown b/gentle-introduction/it/07-Inside-the-View-Layer.markdown index bbe5549..8354089 100644 --- a/gentle-introduction/it/07-Inside-the-View-Layer.markdown +++ b/gentle-introduction/it/07-Inside-the-View-Layer.markdown @@ -215,7 +215,7 @@ Per esempio, se molti template dell'applicazione hanno bisogno di utilizzare lo [php] -Ma questo non è un modo molto pulito per gestire un frammento, soprattutto perché possono esserci nomi di variabili differenti tra il frammento e i vari template che lo includono. Inoltre, il sistema per la cache di symfony (descritto nel Capitolo 12) non ha modo di rilevare un include, quindi il frammento non può essere messo in cache indipendentemente dal template. Symfony fornisce tre tipi alternativi di frammenti di codice per sostituire gli `include`: +Ma questo non è un modo molto pulito per gestire un frammento, soprattutto perché possono esserci nomi di variabili differenti tra il frammento e i vari template che lo includono. Inoltre, il sistema per la cache di symfony (descritto nel capitolo 12) non ha modo di rilevare un include, quindi il frammento non può essere messo in cache indipendentemente dal template. Symfony fornisce tre tipi alternativi di frammenti di codice per sostituire gli `include`: * Se la logica è leggera, basterà includere un file template che ha accesso ad alcuni dati che gli vengono passati. Per questo si userà un partial. * Se la logica è più pesante (ad esempio, se è necessario accedere al modello dei dati e/o modificare il contenuto in base alla sessione), è preferibile separare la presentazione dalla logica. Per questo, si userà un component. @@ -279,7 +279,7 @@ Listato 7-10 - Il partial ora può usare la variabile, in `miomodulo/templates/_ >Tutti gli helper fin'ora sono stati chiamati da ``. L'helper partial, però, è chiamato semplicemente da ``, senza `echo`, in modo che abbia un comportamento simile al normale comando PHP `include()`. Se si ha bisogno di una funzione che restituisca il contenuto di un partial senza visualizzarlo, utilizzare `get_partial()`. Tutti gli helper `include_` descritti in questo capitolo hanno una controparte `get_` che può essere chiamata insieme al comando `echo`. >**TIP** ->Invece di visualizzare un template, una azione può restituire un partial o un component. I metodi `renderPartial()` e `renderComponent()` della classe dell'azione promuovono la riusabilità del codice. Inoltre sfruttano la possibilità dei partial di essere messi in cache (vedere il Capitolo 12). Le variabili definite nell'azione verranno passate automaticamente al partial/component, a meno che non si definisca un array associativo di varibili come secondo paramentro del metodo. +>Invece di visualizzare un template, una azione può restituire un partial o un component. I metodi `renderPartial()` e `renderComponent()` della classe dell'azione promuovono la riusabilità del codice. Inoltre sfruttano la possibilità dei partial di essere messi in cache (vedere il capitolo 12). Le variabili definite nell'azione verranno passate automaticamente al partial/component, a meno che non si definisca un array associativo di varibili come secondo paramentro del metodo. > > [php] > public function executeFoo() @@ -299,7 +299,7 @@ Listato 7-10 - Il partial ora può usare la variabile, in `miomodulo/templates/_ ### Component -Nel Capitolo 2, il primo script di esempio è stato spezzato in due parti per separare la logica dalla presentazione. Proprio come il pattern MVC si applica alle azioni e ai template, può essere necessario dividere un partial in una parte di logica e in una parte di presentazione. In tal caso, è necessario utilizzare un componente. +Nel capitolo 2, il primo script di esempio è stato spezzato in due parti per separare la logica dalla presentazione. Proprio come il pattern MVC si applica alle azioni e ai template, può essere necessario dividere un partial in una parte di logica e in una parte di presentazione. In tal caso, è necessario utilizzare un componente. Un componente è come una azione, salvo il fatto che è molto più veloce. La logica di un componente è all'interno di una classe che eredita da `sfComponents`, situata in un file `actions/components.class.php`. La sua presentazione è è messa in un partial. I metodi di una classe `sfComponents` iniziano con la parola `execute`, proprio come le azioni e possono passare variabili ai loro controparti della presentazione nello stesso modo con cui le azioni passano variabili. I partial che vengono utilizzati come presentazione per componenti sono nominati con lo stesso nome del componente (senza l'`execute`, ma con una sottolineatura iniziale). La Tabella 7-1 compara le convenzioni per i nomi per azioni e componenti. @@ -594,7 +594,7 @@ I setter dell'header sono molto potenti in symfony. Gli header sono inviati il p echo $response->getContentType(); => 'text/xml; charset=utf-8' -Il codice di stato delle risposte di symfony è compatibile con la specifica HTTP. Le eccezioni restituiscono uno stato 500, le pagine non trovate restituiscono 404, le pagine normali restituiscono uno stato 200, le pagine non modificate possono essere ridotte a un semplice header con il codice di stato 304 (vedere il Capitolo 12 per maggiori dettagli) e così via. Ma è possibile sovrascrivere questi valori predefiniti impostando il proprio codice di stato nell'azione con il metodo response `setStatusCode()`. È possibile specificare un codice personalizzato e un messaggio personalizzato, o semplicemente un codice personalizzato, nel qual caso, symfony aggiunge un messaggio generico per questo codice. +Il codice di stato delle risposte di symfony è compatibile con la specifica HTTP. Le eccezioni restituiscono uno stato 500, le pagine non trovate restituiscono 404, le pagine normali restituiscono uno stato 200, le pagine non modificate possono essere ridotte a un semplice header con il codice di stato 304 (vedere il capitolo 12 per maggiori dettagli) e così via. Ma è possibile sovrascrivere questi valori predefiniti impostando il proprio codice di stato nell'azione con il metodo response `setStatusCode()`. È possibile specificare un codice personalizzato e un messaggio personalizzato, o semplicemente un codice personalizzato, nel qual caso, symfony aggiunge un messaggio generico per questo codice. [php] $response->setStatusCode(404, 'Questa pagina non esiste'); diff --git a/gentle-introduction/it/08-Inside-the-Model-Layer-Doctrine.markdown b/gentle-introduction/it/08-Inside-the-Model-Layer-Doctrine.markdown index 796c9c5..60f098a 100644 --- a/gentle-introduction/it/08-Inside-the-Model-Layer-Doctrine.markdown +++ b/gentle-introduction/it/08-Inside-the-Model-Layer-Doctrine.markdown @@ -6,23 +6,23 @@ Gran parte della trattazione finora è stata dedicata alla costruzione di pagine Questo capitolo spiega come creare un modello di dati a oggetti e come accedere ai dati e modificarli con Doctrine. Viene anche trattata l'integrazione di Doctrine con symfony. >**TIP** ->Se si vuole utilizzare Propel al posto di Doctrine, leggere l'Appendice A che contiene le stesse informazioni ma riferite a Propel. +>Se si vuole utilizzare Propel al posto di Doctrine, leggere l'Appendice A, che contiene le stesse informazioni ma riferite a Propel. Perché usare un ORM e un livello per l'astrazione? -------------------------------------------------- I database sono relazionali. PHP 5 e symfony sono orientati agli oggetti. Per poter accedere nel modo più efficace al database in un contesto orientato agli oggetti, è indispensabile una interfaccia per tradurre la logica degli oggetti nella logica relazionale. Come spiegato nel capitolo 1, questa interfaccia è chiamata Object-Relational Mapping (ORM), ed è costituita di oggetti che forniscono l'accesso ai dati e mantengono le business rules all'interno di se stessi. -Il vantaggio principale di un ORM è la riutilizzabilità, che consente ai metodi di un oggetto di tipo dato, di essere chiamato da varie parti dell'applicazione, anche da diverse applicazioni. Il livello ORM incapsula anche la logica dei dati, ad esempio, il calcolo del punteggio degli utenti di un forum basato su quanti contributi sono stati fatti e quanto sono popolari. Quando una pagina deve visualizzare un tale punteggio degli utenti, basta chiamare semplicemente un metodo nel modello dei dati, senza preoccuparsi dei dettagli del calcolo. Se in seguito bisogna modificare il calcolo, sarà sufficiente modificare il metodo nel modello, lasciando il resto dell'applicazione invariata. +Il vantaggio principale di un ORM è la riusabilità, che consente ai metodi di un oggetto di tipo dato, di essere chiamato da varie parti dell'applicazione, anche da diverse applicazioni. Il livello ORM incapsula anche la logica dei dati, ad esempio, il calcolo del punteggio degli utenti di un forum basato su quanti contributi sono stati fatti e quanto sono popolari. Quando una pagina deve visualizzare un tale punteggio degli utenti, basta chiamare semplicemente un metodo nel modello dei dati, senza preoccuparsi dei dettagli del calcolo. Se in seguito bisogna modificare il calcolo, sarà sufficiente modificare il metodo nel modello, lasciando il resto dell'applicazione invariata. -Usare oggetti al posto di record e classi al posto di tabelle, ha un altro vantaggio: la possibilità di aggiungere agli oggetti nuove funzioni di accesso che non necessariamente corrispondono a una colonna in una tabella. Per esempio, se si ha una tabella chiamata `cliente` con due campi chiamati `nome` e `cognome`, si potrebbe volere la possibilità di chiedere solo il `Nome`. In un mondo orientato agli oggetti, basta aggiungere un nuovo metodo accessor alla classe `Cliente`, come si può vedere nel Listato 8-1. Dal punto di vista dell'applicativo, non vi è alcuna differenza tra `Nome`, `Cognome`, e `NomePersona`: sono tutti attributi della classe `Cliente`. Solo la classe stessa può determinare quali attributi corrispondono a una colonna del database. +Usare oggetti al posto di record e classi al posto di tabelle, ha un altro vantaggio: la possibilità di aggiungere agli oggetti nuove funzioni di accesso che non necessariamente corrispondono a una colonna in una tabella. Per esempio, se si ha una tabella chiamata `cliente` con due campi chiamati `nome` e `cognome`, si potrebbe volere la possibilità di chiedere solo il `Nome`. In un mondo orientato agli oggetti, basta aggiungere un nuovo metodo di accesso alla classe `Cliente`, come si può vedere nel Listato 8-1. Dal punto di vista dell'applicativo, non vi è alcuna differenza tra `Nome`, `Cognome`, e `NomePersona`: sono tutti attributi della classe `Cliente`. Solo la classe stessa può determinare quali attributi corrispondono a una colonna del database. -Listato 8-1 - Il metodo accessor maschera la struttura della tabella in una classe del modello +Listato 8-1 - Il metodo di accesso maschera la struttura della tabella in una classe del modello [php] - public function getNomePersona() + public function getName() { - return $this->getNome().' '.$this->getCognome(); + return $this->getFirstName().' '.$this->getLastName(); } Tutte le funzioni ripetute di accesso ai dati e la business logic dei dati stessi, possono essere tenute in tali oggetti. Supponiamo di avere una classe `ShoppingCart` in cui si tenere gli `Articoli` (che sono oggetti). Per ottenere l'importo totale del carrello della spesa, necessario per il pagamento, bisogna scrivere un metodo personalizzato per incapsulare il calcolo effettivo, come mostrato nel Listato 8-2. @@ -30,22 +30,22 @@ Tutte le funzioni ripetute di accesso ai dati e la business logic dei dati stess Listato 8-2 - Il metodo accessor maschera la logica dei dati [php] - public function getTotale() + public function getTotal() { - $totale = 0; - foreach ($this->getArticoli() as $articolo) + $total = 0; + foreach ($this->getItems() as $item) { - $totale += $articolo->getPrezzo() * $articolo->getQuantita(); + $total += $item->getPrice() * $item->getQuantity(); } - return $totale; + return $total; } -C'è un altro punto importante da considerare quando si realizzano delle procedure di accesso ai dati: ogni database utilizza una variante diversa di sintassi SQL. Il passaggio a un altro DataBase Management System (DBMS) costringe a riscrivere parte delle query SQL che sono state progettate per quello precedente. Costruendo le query utilizzando una sintassi indipendente dal database e lasciando la traduzione reale nell'SQL a un componente di terze parti, è possibile cambiare il tipo di database senza troppi problemi. Questo è l'obiettivo del livello di astrazione del database. Costringe a usare una sintassi specifica per le query e fa il lavoro sporco di conformarsi alle particolarità del DBMS e di ottimizzare il codice SQL. +C'è un altro punto importante da considerare quando si realizzano delle procedure di accesso ai dati: ogni database utilizza una variante diversa di sintassi SQL. Il passaggio a un altro database costringe a riscrivere parte delle query SQL che sono state progettate per quello precedente. Costruendo le query utilizzando una sintassi indipendente dal database e lasciando la traduzione reale del codice SQL a un componente di terze parti, è possibile cambiare il tipo di database senza troppi problemi. Questo è l'obiettivo del livello di astrazione del database. Costringe a usare una sintassi specifica per le query e fa il lavoro sporco di conformarsi alle particolarità del database e di ottimizzare il codice SQL. Il principale vantaggio del livello di astrazione è la portabilità, perché rende possibile il passaggio a un'altra base di dati, anche nel bel mezzo di un progetto. Si supponga di dover scrivere rapidamente un prototipo per un'applicazione, ma il cliente non ha ancora deciso quale sistema di base dati può essere la più adatto alle sue esigenze. Si può cominciare a costruire l'applicazione con SQLite, per esempio e passare a MySQL, PostgreSQL, Oracle quando il cliente ha fatto la scelta. Per fare il cambiamento, basta cambiare una riga in un file di configurazione. -Symfony usa Propel o Doctrine come ORM, e questi usano oggetti PHP per l'astrazione dei dati del database. Queste due componenti di terze parti, entrambi sviluppati dal team di Propel e Doctrine, sono perfettamente integrati in symfony, ed è possibile considerarli come parte del framework. La loro sintassi e le loro convenzioni, descritte in questo capitolo, sono state adattate in modo da differenziarsi il meno possibile da quelle di symfony. +Symfony usa Propel o Doctrine come ORM, e questi usano oggetti PHP per l'astrazione dei dati del database. Queste due componenti di terze parti, entrambi sviluppati dal team di Propel e Doctrine, sono perfettamente integrati in symfony ed è possibile considerarli come parte del framework. La loro sintassi e le loro convenzioni, descritte in questo capitolo, sono state adattate in modo da differenziarsi il meno possibile da quelle di symfony. >**NOTE** >In un progetto symfony, tutte le applicazioni condividono lo stesso modello. Questo è un punto fondamentale a livello di progetto: raggruppare le applicazioni che si basano su regole di business comuni. Questa è la ragione per cui il modello è indipendente dalle applicazioni e i file del modello sono memorizzati in una cartella `lib/model/` nella radice del progetto. @@ -59,8 +59,7 @@ La sintassi di symfony per gli schemi utilizza il formato YAML. I file `schema.y ### Esempio di schema -Come tradurre la struttura del database in uno schema? Un esempio è il modo migliore per capirlo. Immaginiamo di avere il database di un blog con due tabelle: - `blog_articolo` e `blog_commento`, con la struttura mostrata in Figura 8-1. +Come tradurre la struttura del database in uno schema? Un esempio è il modo migliore per capirlo. Immaginiamo di avere il database di un blog con due tabelle: `blog_articolo` e `blog_commento`, con la struttura mostrata in Figura 8-1. Figura 8-1 - Struttura delle tabelle del database di un blog @@ -71,30 +70,30 @@ Il relativo file `schema.yml` dovrebbe apparire come nel Listato 8-3. Listato 8-3 - Esempio di file `schema.yml` [yml] - Articolo: + Article: actAs: [Timestampable] - tableName: blog_articolo + tableName: blog_article columns: id: type: integer primary: true autoincrement: true - titolo: string(255) - contenuto: clob + title: string(255) + content: clob - Commento: + Comment: actAs: [Timestampable] - tableName: blog_commento + tableName: blog_comment columns: id: type: integer primary: true autoincrement: true - articolo_id: integer - autore: string(255) - contenuto: clob + article_id: integer + author: string(255) + content: clob relations: - Articolo: + Article: onDelete: CASCADE foreignAlias: Comments @@ -107,7 +106,7 @@ In un file `schema.yml`, la prima chiave rappresenta un nome del modello. È pos Un modello può avere attributi speciali, tra cui la `tableName` (il nome della tabella del database relativa al modello). Se non si specifica la `tableName` per un modello, Doctrine lo crea facendo una versione con sottolineatura del nome del modello. >**TIP** ->La convenzione della sottolineatura aggiunge sottolineature tra le parole e utilizza solo caratteri minuscoli. Le versioni sottolineate predefinite di `Articolo` e `Commento` sono `articolo` e `commento`. +>La convenzione della sottolineatura aggiunge sottolineature tra le parole e utilizza solo caratteri minuscoli. Le versioni sottolineate predefinite di `Article` e `Comment` sono `article` e `comment`. Un modello contiene colonne. Il valore della colonna può essere definito in due modi diversi: @@ -129,15 +128,15 @@ Lo schema è usato per costruire le classi del modello nel livello ORM. Per risp La digitazione del comando lancerà l'analisi dello schema e la generazione delle classe base del modello dei dati nella cartella `lib/model/doctrine/base` del progetto: - * `BaseArticolo.php` - * `BaseCommento.php` + * `BaseArticle.php` + * `BaseComment.php` Inoltre nella cartella `lib/model/doctrine` verranno create le classi personalizzate del modello : - * `Articolo.php` - * `ArticoloTable.php` - * `Commento.php` - * `CommentoTable.php` + * `Article.php` + * `ArticleTable.php` + * `Comment.php` + * `CommentTable.php` Sono stati definiti solo due modelli e ci si ritrova con sei file. Non c'è nulla di sbagliato, ma questo risultato merita una ulteriore spiegazione. @@ -156,32 +155,32 @@ Il Listato 8-4 mostra un esempio di una classe personalizzata del modello, così Listato 8-4 - Esempio di file di una classe del modello, in `lib/model/doctrine/Article.php` [php] - class Articolo extends BaseArticolo + class Article extends BaseArticle { } -La classe Articolo eredita ogni cosa della classe `BaseArticolo`, ma modifiche nello schema non hanno effetti su Articolo. +La classe Articolo eredita ogni cosa della classe `BaseArticle`, ma modifiche nello schema non hanno effetti su Articolo. Il meccanismo delle classi personalizzate che estendono delle classi base consente di iniziare lo sviluppo, anche senza conoscere il modello relazionale finale del database. La relativa struttura dei file rende il modello sia personalizzabile che estendibile. ### Classi di oggetti e tabelle -`Articolo` e `Commento` sono classi di oggetti che rappresentano un record nel database. Forniscono accesso alle colonne di un record e ai relativi record. Questo significa che si è in grado di sapere il titolo di un articolo chiamando un metodo di un oggetto Articolo, come nell'esempio mostrato nel Listato 8-5. +`Article` e `Comment` sono classi di oggetti che rappresentano un record nel database. Forniscono accesso alle colonne di un record e ai relativi record. Questo significa che si è in grado di sapere il titolo di un articolo chiamando un metodo di un oggetto Articolo, come nell'esempio mostrato nel Listato 8-5. Listato 8-5 - Nella classe dell'oggetto sono disponibili dei metodi getter per tutte le colonne del record [php] - $articolo = new Articolo(); + $article = new Article(); // ... - $titolo = $articolo->getTitolo(); + $title = $article->getTitle(); -`ArticoloTable` e `CommentoTable` sono classi per le tabelle; cioè classi che contengono metodi pubblici che permettono di operare sulle tabelle. Essi forniscono un modo per recuperare i record dalle tabelle. I loro metodi di solito restituiscono un oggetto o un insieme di oggetti della relativa classe dell'oggetto, come mostrato nel Listato 8-6 +`ArticleTable` e `CommentTable` sono classi per le tabelle; cioè classi che contengono metodi pubblici che permettono di operare sulle tabelle. Essi forniscono un modo per recuperare i record dalle tabelle. I loro metodi di solito restituiscono un oggetto o un insieme di oggetti della relativa classe dell'oggetto, come mostrato nel Listato 8-6 Listato 8-6 - Nella classe della tabella sono disponibili dei metodi pubblici per recuperare i record [php] - // $articolo è una istanza della classe Articolo - $articolo = Doctrine_Core::getTable('Articolo')->find(123); + // $article è una istanza della classe Article + $article = Doctrine_Core::getTable('Article')->find(123); Accesso ai dati --------------- @@ -198,56 +197,56 @@ Campo, colonna| Proprietà ### Recuperare il valore della colonna -Quando symfony costruisce il modello, crea una classe base di un oggetto per ciascuno dei modelli definiti nel file `schema.yml`. Ciascuna di queste classi è dotata di accessor e mutator predefiniti generati in base alle definizioni della colonna: i metodi `new`, `getXXX()` e `setXXX()` aiutano a creare oggetti e forniscono accesso alle proprietà dell'oggetto, come mostrato nel Listato 8-7. +Quando symfony costruisce il modello, crea una classe base di un oggetto per ciascuno dei modelli definiti nel file `schema.yml`. Ciascuna di queste classi è dotata di accessori e modificatori predefiniti generati in base alle definizioni della colonna: i metodi `new`, `getXXX()` e `setXXX()` aiutano a creare oggetti e forniscono accesso alle proprietà dell'oggetto, come mostrato nel Listato 8-7. Listato 8-7 - Metodi generati nella classe dell'oggetto [php] - $articolo = new Articolo(); - $articolo->setTitolo('Il mio primo articolo'); - $articolo->setContenuto("Questo è il mio primo articolo.\n Spero che possa piacere!"); + $article = new Article(); + $article->setTitle('Il mio primo articolo'); + $article->setContent("Questo è il mio primo articolo.\n Spero che possa piacere!"); - $titolo = $articolo->getTitolo(); - $contenuto = $articolo->getContenuto(); + $title = $article->getTitle(); + $content = $article->getContent(); >**NOTE** ->La classe generata per l'oggetto è chiamata `Articolo` ma nel database il dato è memorizzato in una tabella chiamata `blog_articolo`. Se nello schema `tableName` non fosse stato definito, la classe sarebbe stata chiamata `articolo`. I metodi accessor e mutator usano una variante camelCase dei nomi delle colonne, quindi il metodo `getTitolo()` recupera il valore della colonna `titolo`. +>La classe generata per l'oggetto è chiamata `Article` ma nel database il dato è memorizzato in una tabella chiamata `blog_articolo`. Se nello schema `tableName` non fosse stato definito, la classe sarebbe stata chiamata `article`. I metodi accessor e mutator usano una variante camelCase dei nomi delle colonne, quindi il metodo `getTitolo()` recupera il valore della colonna `titolo`. Per impostare molti campi in una sola volta, si può usare il metodo `fromArray()`, disponibile anche per ciascuna classe dell'oggetto, come mostrato nel Listato 8-8. Listato 8-8 - Il metodo `fromArray()` è un setter multiplo [php] - $articolo->fromArray(array( - 'Titolo' => 'Il mio primo articolo', - 'Contenuto' => 'Questo è il mio primo articolo.\n Spero che possa piacere!', + $article->fromArray(array( + 'Title' => 'Il mio primo articolo', + 'Content' => 'Questo è il mio primo articolo.\n Spero che possa piacere!', )); ### Recuperare i record correlati La colonna `articolo_id` della tabella `blog_commento` definisce implicitamente una chiave esterna alla tabella `blog_articolo`. Ogni commento è correlato a un articolo e un articolo può avere molti commenti. Le classi generate contengono cinque metodi per tradurre queste relazioni in una modalità orientata agli oggetti. Sono i seguenti: - * `$commento->getArticolo()`: Per ottenere gli oggetti relativi ad `Articolo` - * `$commento->getArticoloId()`: Per ottenere l'ID del relativo oggetto `Articolo` - * `$commento->setArticolo($articolo)`: Per definire il relativo oggetto `Articolo` - * `$commento->setArticoloId($id)`: Per definire il relativo oggetto `Articolo` da un ID - * `$articolo->getCommenti()`: Per ottenere i relativi oggetti `Commento` + * `$comment->getArticle()`: Per ottenere gli oggetti relativi ad `Article` + * `$comment->getArticleId()`: Per ottenere l'ID del relativo oggetto `Article` + * `$comment->setArticolo($article)`: Per definire il relativo oggetto `Article` + * `$comment->setArticoloId($id)`: Per definire il relativo oggetto `Article` da un ID + * `$article->getCommenti()`: Per ottenere i relativi oggetti `Comment` -I metodi `getArticoloId()` e `setArticoloId()` mostrano che si può considerare la colonna `articolo_id` come una normale colonna e impostare le relazioni a mano, ma non è una cosa molto utile. Il vantaggio di un approccio orientato agli oggetti è molto più evidente nei tre altri metodi. Il Listato 8-9 mostra come usare i metodi setter generati. +I metodi `getArticleId()` e `setArticoloId()` mostrano che si può considerare la colonna `articolo_id` come una normale colonna e impostare le relazioni a mano, ma non è una cosa molto utile. Il vantaggio di un approccio orientato agli oggetti è molto più evidente nei tre altri metodi. Il Listato 8-9 mostra come usare i metodi setter generati. Listato 8-9 - Le chiavi esterne sono tradotte in un setter speciale [php] - $commento = new Commento(); - $commento->setAutore('Fabrizio'); - $commento->setContenuto('Fantastico, è il miglior articolo che ho letto!'); + $comment = new Comment(); + $comment->setAuthor('Fabrizio'); + $comment->setContent('Fantastico, è il miglior articolo che ho letto!'); - // Collega questo commento al precedente oggetto $articolo - $commento->setArticolo($articolo); + // Collega questo commento al precedente oggetto $article + $comment->setArticle($article); // Sintassi alternativa // Ha senso solo se l'oggetto è stato già salvato nel database - $commento->setArticoloId($articolo->getId()); + $comment->setArticleId($article->getId()); Il Listato 8-10 mostra come usare i metodi getter generati. Mostra anche come concatenare le chiamate di metodi sugli oggetti del modello. @@ -255,27 +254,27 @@ Listato 8-10 - Le chiavi esterne sono tradotte in getter speciali [php] // Relazione molti a uno - echo $commento->getArticolo()->getTitolo(); + echo $comment->getArticle()->getTitolo(); => Il mio primo articolo - echo $commento->getArticolo()->getContenuto(); + echo $comment->getArticle()->getContenuto(); => Questo è il mio primo articolo. Spero che possa piacere! // Relazione uno a molti - $commenti = $articolo->getCommenti(); + $commenti = $article->getComments(); -Il metodo `getArticolo()` restituisce un oggetto della classe `Articolo`, che trae beneficio dall'accessor `getTitolo()`. Questa è una operazione migliore rispetto a fare la join da soli, la quale può necessitare di qualche riga di codice in più (partendo dalla chiamata `$commento->getArticoloId()`). +Il metodo `getArticle()` restituisce un oggetto della classe `Article`, che trae beneficio dall'accessor `getTitolo()`. Questa è una operazione migliore rispetto a fare la join da soli, la quale può necessitare di qualche riga di codice in più (partendo dalla chiamata `$comment->getArticleId()`). -La variabile `$commenti` nel Listato 8-10 contiene un array di oggetti della classe `Commento`. Si può visualizzare il primo con `$commenti[0]` o iterare sulla collezione con `foreach ($commenti as $commento)`. +La variabile `$commenti` nel Listato 8-10 contiene un array di oggetti della classe `Comment`. Si può visualizzare il primo con `$commenti[0]` o iterare sulla collezione con `foreach ($commenti as $comment)`. ### Salvare e cancellare i dati Chiamando il costruttore `new`, viene creato un nuovo oggetto, ma non un nuovo record nella tabella `blog_articolo`. La modifica dell'oggetto non ha effetto sul database. Per salvare i dati nel database, bisogna chiamare il metodo `save()` dell'oggetto. [php] - $articolo->save(); + $article->save(); -L'ORM riesce a riconoscere le relazioni tra oggetti, quindi salvando l'oggetto `$articolo` viene anche salvato l'oggetto `$commento` a esso collegato. L'ORM sa anche se l'oggetto salvato ha una controparte esistente nel database , quindi la chiamata `save()` a volte è tradotta in SQL con `INSERT` e a volte con `UPDATE`. La chiave primaria è impostata automaticamente dal metodo `save()`, quindi dopo aver salvato, si può recuperare la nuova chiave primaria con `$articolo->getId()`. +L'ORM riesce a riconoscere le relazioni tra oggetti, quindi salvando l'oggetto `$article` viene anche salvato l'oggetto `$comment` a esso collegato. L'ORM sa anche se l'oggetto salvato ha una controparte esistente nel database , quindi la chiamata `save()` a volte è tradotta in SQL con `INSERT` e a volte con `UPDATE`. La chiave primaria è impostata automaticamente dal metodo `save()`, quindi dopo aver salvato, si può recuperare la nuova chiave primaria con `$article->getId()`. >**TIP** >Si può controllare se un oggetto è nuovo, chiamando `isNew()`. Se si vuole sapere se un oggetto è stato modificato per eventualmente evitare il salvataggio, basta chiamare il metodo `isModified()`. @@ -285,25 +284,25 @@ Se si leggono commenti ai propri articoli, si potrebbe cambiare idea circa l'opp Listato 8-11 - Cancellare i record dal database con il metodo `delete()` sul relativo oggetto [php] - foreach ($articolo->getCommenti() as $commento) + foreach ($article->getCommenti() as $comment) { - $commento->delete(); + $comment->delete(); } ### Recuperare i record tramite chiave primaria -Se si conosce la chiave primaria di un certo record usare il metodo `find()` della classe della tabella per recuperare il relativo oggetto. +Se si conosce la chiave primaria di un certo record, usare il metodo `find()` della classe della tabella per recuperare il relativo oggetto. [php] - $articolo = Doctrine_Core::getTable('Articolo')->find(7); + $article = Doctrine_Core::getTable('Article')->find(7); -Il file `schema.yml` definisce il campo `id` come chiave primaria della tabella `blog_articolo`, quindi questo comando restituirà l'articolo che ha `id` 7. Essendo stata utilizzata la chiave primaria, sappiamo che verrà restituito solo un record; la variabile `$articolo` contiene un oggetto della classe `Articolo`. +Il file `schema.yml` definisce il campo `id` come chiave primaria della tabella `blog_articolo`, quindi questo comando restituirà l'articolo che ha `id` 7. Essendo stata utilizzata la chiave primaria, sappiamo che verrà restituito solo un record; la variabile `$article` contiene un oggetto della classe `Article`. -In alcuni casi, una chiave primaria piò essere costituita da più di una colonna. Per gestire questi casi, il metodo `find()` accetta parametri multipli, uno per ciascuna chiave primaria di colonna. +In alcuni casi, una chiave primaria può essere costituita da più di una colonna. Per gestire questi casi, il metodo `find()` accetta parametri multipli, uno per ciascuna chiave primaria di colonna. ### Recuperare i record tramite Doctrine_Query -Quando si vuole recuperare più di un record, bisogna chiamare il metodo `createQuery()` della classe della tabella corrispondente agli oggetti che si vogliono recuperare. Ad esempio, per recuperare oggetti della classe `Articolo`, chiamare `Doctrine_Core::getTable('Articolo')->createQuery()->execute()`. +Quando si vuole recuperare più di un record, bisogna chiamare il metodo `createQuery()` della classe della tabella corrispondente agli oggetti che si vogliono recuperare. Ad esempio, per recuperare oggetti della classe `Article`, chiamare `Doctrine_Core::getTable('Article')->createQuery()->execute()`. Il primo parametro del metodo `execute()` è un array di parametri, che è l'array di valori per sostituire tutti i segnaposto trovati nella query. @@ -312,7 +311,7 @@ Una `Doctrine_Query` vuota restituisce tutti gli oggetti della classe. Ad esempi Listato 8-12 - Recuperare i record di Doctrine_Query con `createQuery()`--Query vuota [php] - $q = Doctrine_Core::getTable('Articolo')->createQuery(); + $q = Doctrine_Core::getTable('Article')->createQuery(); $articoli = $q->execute(); // Verrà generata la seguente query SQL @@ -379,7 +378,7 @@ Infine, se si vuole che venga restituito solo il primo oggetto, sostituire la ch >**TIP** >Quando una query `execute()` restituisce un grosso numero di risultati, si potrebbe voler visualizzare solo un sottoinsieme di questi nella risposta. Symfony fornisce una classe per la paginazione chiamata `sfDoctrinePager`, che automatizza la paginazione dei risultati. -### Utilizzo di query SQL raw +### Utilizzo di query in puro SQL A volte non si vogliono recuperare oggetti, ma solo risultati sintetici calcolati dal database. Ad esempio, per ottenere l'ultima data di creazione tra tutti gli articoli, non ha senso recuperare tutti gli articoli e ciclare sull'array. Si preferirà chiedere al database di restituire solo il risultato, perché in questo modo verrà saltato il processo di idratazione. @@ -418,12 +417,12 @@ La buona notizia è che Doctrine ha un comportamento `Timestampable` che gestir Listato 8-16 - Le colonne `created_at` e `updated_at` Columns sono gestite automaticamente [php] - $commento = new Commento(); - $commento->setAutore('Fabrizio'); - $commento->save(); + $comment = new Commento(); + $comment->setAutore('Fabrizio'); + $comment->save(); // Mostra la creazione della data - echo $commento->getCreatedAt(); + echo $comment->getCreatedAt(); => [data dell'operazione di INSERT nel database] >**SIDEBAR** @@ -441,12 +440,12 @@ Listato 8-16 - Le colonne `created_at` e `updated_at` Columns sono gestite autom > $this->articoli = $tag->getArticoliPopolari(10); > } > ->L'azione crea un oggetto della classe `Tag` dal parametro della request. Tutto il codice necessario per interrogare il database si trova nel metodo `getArticoliPopolari` di questa classe. Rende l'azione più leggibile e il codice del modello può facilmente venire riutilizzato in un'altra azione. +>L'azione crea un oggetto della classe `Tag` dal parametro della richiesta. Tutto il codice necessario per interrogare il database si trova nel metodo `getArticoliPopolari` di questa classe. Rende l'azione più leggibile e il codice del modello può facilmente venire riutilizzato in un'altra azione. > >Spostare il codice in un posto più appropriato è una delle tecniche della rifattorizzazione. Se la si fa spesso, il codice sarà semplice da mantenere e da comprendere da parte di altri sviluppatori. Una buona regola per capire quando fare refactoring nel livello dei dati, è che il codice di una azione raramente deve contenere più di dieci righe di codice PHP. Connessioni al database ---------------------------- +------------------------ Il modello del dati è indipendente dal database usato, ma dovrà sicuramente utilizzare un database. Le minime informazioni richieste da symfony per inviare richieste al database del progetto sono il nome, le credenziali e il tipo di database. Queste impostazioni per la connessione possono essere configurate passando il nome della sorgente dati (DSN, data source name) al task `configure:database`: @@ -514,7 +513,7 @@ I metodi generati del modello sono utili ma a volte non sufficienti. Non appena Si possono aggiungere nuovi metodi alle classi vuote del modello generate nella cartella `lib/model/doctrine`. Usare `$this` per chiamare i metodi dell'oggetto corrente e usare `self::` per chiamare metodi statici della classe corrente. Ricordarsi che le classi personalizzate ereditano i metodi dalle classi `Base` presenti nella cartella `lib/model/doctrine/base`. -Ad esempio, per l'oggetto `Articolo` generato basandosi sul Listato 8-3, si può aggiungere un metodo magico `__toString()` in modo che faccendo l'echo di un oggetto della classe `Articolo` venga visualizzato il suo titolo, come mostrato nel Listato 8-20. +Ad esempio, per l'oggetto `Article` generato basandosi sul Listato 8-3, si può aggiungere un metodo magico `__toString()` in modo che faccendo l'echo di un oggetto della classe `Article` venga visualizzato il suo titolo, come mostrato nel Listato 8-20. Listato 8-20 - Personalizzazione del modello, in `lib/model/doctrine/Articolo.php` @@ -548,17 +547,17 @@ I nuovi metodi sono disponibili nello stesso modo di quelli generati, come mostr Listato 8-22 - Usare i metodi personalizzati dei modelli è come usare i metodi generati [php] - $articoli = Doctrine_Core::getTable('Articolo')->getTuttoOrdinatoPerData(); - foreach ($articoli as $articolo) + $articoli = Doctrine_Core::getTable('Article')->getTuttoOrdinatoPerData(); + foreach ($articoli as $article) { - echo $articolo; // Chiamerà il metodo magico __toString() + echo $article; // Chiamerà il metodo magico __toString() } ### Sovrascrivere i metodi esistenti Se alcuni dei metodi generati nelle classi `Base` non si adattano alle proprie esigenze, si può sovrascriverle nella classe personalizzata. Basta fare in modo di utilizzare la stessa firma nel metodo (cioè lo stesso numero di argomenti). -Ad esempio, il metodo `$article->getCommenti()` restituisce una collezione di oggetti `Commento`, in nessun ordine particolare. Se si vogliono avere i risultati ordinati per data di creazione, con gli ultimi commenti messi all'inizio, allora bisogna creare il metodo `getCommenti()` come mostrato nel Listato 8-23. +Ad esempio, il metodo `$article->getCommenti()` restituisce una collezione di oggetti `Comment`, in nessun ordine particolare. Se si vogliono avere i risultati ordinati per data di creazione, con gli ultimi commenti messi all'inizio, allora bisogna creare il metodo `getCommenti()` come mostrato nel Listato 8-23. Listato 8-23 - Sovrascrivere i metodi esistenti del modello, in `lib/model/Articolo.php` @@ -594,7 +593,7 @@ Per abilitare i comportamenti nelle classi del modello, è necessario modificare titolo: string(255) contenuto: clob -Dopo aver rigenerato i modelli, il modello `Articolo` ha una colonna slug che è automaticamente impostata con una stringa "amichevole" per le url basata sul titolo. +Dopo aver rigenerato i modelli, il modello `Article` ha una colonna slug che è automaticamente impostata con una stringa "amichevole" per le url basata sul titolo. Alcuni dei comportamenti disponibili per Doctrine sono: @@ -625,7 +624,7 @@ Listato 8-24 - Attributi per le impostazioni del modello L'attributo `export` controlla quale SQL è esportato al database quando vengono create le tabelle per questo modello. Utilizzando il valore `tables` viene solo esportata la struttura della tabella e non le chiavi esterne, gli indici, ecc. -Le tabelle che contengono contenuto localizzato (cioè, diverse versioni del contenuto, in una tabella correlata per l'internazionalizzazione) devono utilizzare il comportamento I18n (si veda il Capitolo 13 per dettagli), come mostrato nel Listato 8-25. +Le tabelle che contengono contenuto localizzato (cioè, diverse versioni del contenuto, in una tabella correlata per l'internazionalizzazione) devono utilizzare il comportamento I18n (si veda il capitolo 13 per dettagli), come mostrato nel Listato 8-25. Listato 8-25 - Il comportamento I18n @@ -636,7 +635,7 @@ Listato 8-25 - Il comportamento I18n fields: [titolo, contenuto] >**SIDEBAR** ->Trattare con più schemi +>Gestire schemi multipli > >Si può avere più di uno schema per applicazione. Symfony considererà tutti i file che finiscono con`.yml` presenti nella cartella `config/doctrine`. Se l'applicazione ha molti modelli, o se alcuni modelli non condividono la stessa connessione, si potrà trovare questo approccio molto utile. > @@ -662,7 +661,7 @@ Listato 8-25 - Il comportamento I18n > resource: string(100) > > ->Entrambi gli schemi condividono la stessa connessione (`doctrine`) e le classi `Articolo` e `Hit` verranno generate sotto la stessa cartella `lib/model/doctrine`. Tutto avviene come se si fosse scritto un solo schema. +>Entrambi gli schemi condividono la stessa connessione (`doctrine`) e le classi `Article` e `Hit` verranno generate sotto la stessa cartella `lib/model/doctrine`. Tutto avviene come se si fosse scritto un solo schema. > >Si possono anche avere schemi diversi che usano connessioni diverse (ad esempio, `doctrine` e `doctrine_bis`, da definire `databases.yml`) e associarli a questa connessione: > @@ -689,7 +688,7 @@ Listato 8-25 - Il comportamento I18n > resource: string(100) > > ->Molte applicazioni usano più di uno schema. In particolare, alcuni plug-in hanno il loro proprio schema per evitare problemi con quelli di altre classi (vedere il capitolo 17 per maggiori dettagli). +>Molte applicazioni usano più di uno schema. In particolare, alcuni plugin hanno il proprio schema, per evitare problemi con quelli di altre classi (vedere il capitolo 17 per maggiori dettagli). ### Dettagli delle colonne @@ -748,11 +747,11 @@ Listato 8-28 - Sintassi alternativa per la chiave esterna onDelete: CASCADE foreignAlias: Articles -### Indexes +### Indici -Si possono aggiungere indici in un modello, sotto la chiave `indexes:`. Se si vogliono definire indici univoci, bisogna usare la sintassi `type: unique`. Per le colonne che richiedono una dimensione, perché sono colonne di testo, la dimensione dell'indice è specificata nello stesso modo della lunghezza della colonna usando le parentesi. Il Listato 8-30 mostra la sintassi alternativa per gli indici. +Si possono aggiungere indici in un modello, sotto la chiave `indexes:`. Se si vogliono definire chiavi univoche, bisogna usare la sintassi `type: unique`. Per le colonne che richiedono una dimensione, perché sono colonne di testo, la dimensione dell'indice è specificata nello stesso modo della lunghezza della colonna, usando le parentesi. Il Listato 8-30 mostra la sintassi alternativa per gli indici. -Listato 8-30 - Indici e indici univoci +Listato 8-30 - Indici e chiavi univoche [yml] Articolo: @@ -785,7 +784,7 @@ Listato 8-30 - Indici e indici univoci Symfony supporta l'internazionalizzazione dei contenuti tramite tabelle dedicate. Questo significa che quando si ha un contenuto da internazionalizzare, viene memorizzato in due tabelle separate: una per le colonne che non cambiano e una per le colonne da internazionalizzare. -Listato 8-33 - Meccanismo I18n +Listato 8-33 - Meccanismo i18n [yml] DbGroup: @@ -797,7 +796,7 @@ Listato 8-33 - Meccanismo I18n ### Comportamenti -I comportamenti sono modificatori dei modelli forniti da plug-in, che aggiungono nuove capacità alle classi di Doctrine. Il capitolo 17 parla più approfonditamente dei comportamenti. I comportamenti si possono definire nello schema, elencandoli per ciascuna tabella, insieme con i loro parametri, sotto la chiave `actAs`. Il Listato 8-34 fornisce un esempio estendendo la classe `Articolo` con il comportamento `Sluggable`. +I comportamenti sono modificatori dei modelli forniti da plugin, che aggiungono nuove capacità alle classi di Doctrine. Il capitolo 17 parla più approfonditamente dei comportamenti. I comportamenti si possono definire nello schema, elencandoli per ciascuna tabella, insieme con i loro parametri, sotto la chiave `actAs`. Il Listato 8-34 fornisce un esempio estendendo la classe `Article` con il comportamento `Sluggable`. Listato 8-34 - Dichiarazione dei comportamenti @@ -809,7 +808,7 @@ Listato 8-34 - Dichiarazione dei comportamenti Non creare il modello due volte ------------------------------- -Lo svantaggio nell'utilizzo di un ORM è che bisogna definire la struttura dati due volte: una per il database e una per il modello a oggetti. Per fortuna, symfony fornisce dei tool a riga di comando per generare l'uno basato sull'altro, in modo da evitare la duplicazione del lavoro. +Lo svantaggio nell'utilizzo di un ORM è che bisogna definire la struttura dati due volte: una per il database e una per il modello a oggetti. Per fortuna, symfony fornisce degli strumenti a riga di comando per generare l'uno basato sull'altro, in modo da evitare la duplicazione del lavoro. ### Creare l'SQL della struttura di un database basandosi su uno schema esistente @@ -824,7 +823,7 @@ Si può usare il file `schema.sql` direttamente per costruire le tabelle. Ad ese $ mysqladmin -u root -p create blog $ mysql -u root -p blog < data/sql/schema.sql -L'SQL generato è utile anche per ricostruire il database in un altro ambiente o per passare a un altro DBMS. +Il codice SQL generato è utile anche per ricostruire il database in un altro ambiente o per passare a un altro DBMS. >**TIP** >La riga di comando offre anche un task per popolare il database con i dati caricati da un file di testo. Vedere il capitolo 16 per maggiori informazioni sul task `doctrine:data-load` e i file delle fixture in YAML. @@ -842,7 +841,7 @@ Dalla struttura del database viene generato un nuovo file `schema.yml` nella car Riepilogo --------- -Symfony usa Doctrine come ORM e PHP Data Objects per il livello di astrazione del database. Ciò significa che è necessario prima descrivere lo schema relazionale del database in YAML prima di generare le classi del modello a oggetti. Poi, in fase di runtime, utilizzare i metodi dell'oggetto e le classi delle tabelle per recuperare informazioni su un record o un insieme di record. È possibile facilmente sovrascrivere ed estendere il modello aggiungendo metodi alle classi personalizzate. Le impostazioni di connessione sono definite in un file `databases.yml`, che può supportare più di una connessione. E la linea di comando contiene dei task speciali per evitare di duplicare la definizione della struttura. +Symfony usa Doctrine come ORM e gli oggetti dei dati di PHP per il livello di astrazione del database. Ciò significa che è necessario prima descrivere lo schema relazionale del database in YAML prima di generare le classi del modello a oggetti. Poi, in fase di runtime, utilizzare i metodi dell'oggetto e le classi delle tabelle per recuperare informazioni su un record o un insieme di record. È possibile sovrascrivere ed estendere facilmente il modello aggiungendo metodi alle classi personalizzate. Le impostazioni di connessione sono definite in un file `databases.yml`, che può supportare più di una connessione. E la linea di comando contiene dei task speciali per evitare di duplicare la definizione della struttura. Il livello del modello è il più complesso del framework symfony. Una delle ragioni di questa complessità è che la manipolazione dei dati è una questione intricata. I problemi di sicurezza correlati sono fondamentali per un sito web e non devono essere ignorati. Un'altra ragione è che symfony è più adatto ad applicazioni di medio-grandi dimensioni in contesto enterprise. In tali applicazioni, le automazioni fornite dal modello di symfony possono davvero rappresentare un guadagno di tempo che vale l'investimento per apprendere il suo funzionamento. diff --git a/gentle-introduction/it/10-Forms.markdown b/gentle-introduction/it/10-Forms.markdown index 27bb916..f70e493 100644 --- a/gentle-introduction/it/10-Forms.markdown +++ b/gentle-introduction/it/10-Forms.markdown @@ -1,5 +1,5 @@ -Chapter 10 - I form -=================== +Capitolo 10 - I form +==================== La visualizzazione degli input di un form, la validazione dei dati inseriti in un form e tutta la casistica particolare del trattamento dei form è uno dei compiti più complessi nello sviluppo web. Fortunatamente, symfony fornisce un'interfaccia semplice verso un potente sottosistema dedicato ai form, e facilita la creazione e la manipolazione con poche linee di codice di form di qualsiasi livello di complessità. @@ -415,7 +415,7 @@ I widget data sono un buon esempio della potenza dei widget in symfony. Un widge ### I widget I18n -Nelle applicazioni multilingua, le date devono essere mostrare in un formato che si accordi con la cultura dell'utente (si veda il Capitolo 13 per dettagli riguardo cultura e localizzazione). Per facilitare questa localizzazione nei form, symfony offre un widget `sfWidgetFormI18nDate`, che si basa sulla `culture` dell'utente per stabilire i parametri di formattazione delle date. È anche possibile specificare un `month_format` per visualizzare una lista drop-down con i nomi dei mesi (nella lingua dell'utente) invece dei numeri. +Nelle applicazioni multilingua, le date devono essere mostrare in un formato che si accordi con la cultura dell'utente (si veda il capitolo 13 per dettagli riguardo cultura e localizzazione). Per facilitare questa localizzazione nei form, symfony offre un widget `sfWidgetFormI18nDate`, che si basa sulla `culture` dell'utente per stabilire i parametri di formattazione delle date. È anche possibile specificare un `month_format` per visualizzare una lista drop-down con i nomi dei mesi (nella lingua dell'utente) invece dei numeri. [php] // Data @@ -741,7 +741,7 @@ Ogni validatore invalido risulta in un messaggio di errore nel campo. Questi mes )) )); -Naturalmente, questi messaggi personalizzati vengono resi nei template attraverso gli helper i18n, così le applicazioni multilingua possono anche tradurre i messaggi di errore personalizzati in un dizionario (si veda il Capitolo 13 per ulteriori dettagli). +Naturalmente, questi messaggi personalizzati vengono resi nei template attraverso gli helper i18n, così le applicazioni multilingua possono anche tradurre i messaggi di errore personalizzati in un dizionario (si veda il capitolo 13 per ulteriori dettagli). ### Applicare un validatore a più campi diff --git a/gentle-introduction/it/13-I18n-and-L10n.markdown b/gentle-introduction/it/13-I18n-and-L10n.markdown index 8bad08a..98e0333 100644 --- a/gentle-introduction/it/13-I18n-and-L10n.markdown +++ b/gentle-introduction/it/13-I18n-and-L10n.markdown @@ -485,7 +485,7 @@ nella stessa cartella. >corretta di una data stringa potrebbe richiedere un po' di tempo, symfony usa una cache >interna per accelerare il processo. Per impostazione predefinita, questa cache usa il >filesystem. Si può configurare la modalità di funzionamento della cache i18n (ad esempio, ->per condividere la cache tra server diversi) in `factories.yml` (vedere Capitolo 19). +>per condividere la cache tra server diversi) in `factories.yml` (vedere capitolo 19). ### Gestire i dizionari @@ -509,7 +509,7 @@ Un altro modo per organizzare i dizionari è quello di dividerli per modulo. Inv scrivere un singolo file `messages.XX.xml` per l'intera applicazione, se ne può scrivere uno in ogni cartella `modules/[nome_modulo]/i18n/`. Questo rende i moduli più indipendenti dall'applicazione, il che è necessario se si vuole riutilizzarli, come in -un plugin (vedere Capitolo 17). +un plugin (vedere capitolo 17). Poiché l'aggiornamento manuale dei dizionari è spesso soggetto a errori, symfony fornisce un task per automatizzare il processo. Il task `i18n:extract` analizza un'applicazione @@ -552,7 +552,7 @@ I seguenti sono altri elementi che potrebbero richiedere traduzione: * Le pagine predefinite di symfony (pagina non trovata, errore interno del server, accesso vietato, ecc.) sono in inglese e devono essere riscritte in una applicazione i18n. Probabilmente si vorrà creare un proprio modulo `default` nell'applicazione e - usare `__()` nei suoi template. Si faccia riferimento al Capitolo 19 per vedere come + usare `__()` nei suoi template. Si faccia riferimento al capitolo 19 per vedere come personalizzare queste pagine. ### Gestire esigenze complesse di traduzione diff --git a/gentle-introduction/it/16-Application-Management-Tools.markdown b/gentle-introduction/it/16-Application-Management-Tools.markdown index 8abbea2..ae429cf 100644 --- a/gentle-introduction/it/16-Application-Management-Tools.markdown +++ b/gentle-introduction/it/16-Application-Management-Tools.markdown @@ -357,7 +357,7 @@ Listato 16-12 - Esempio di script batch, in `lib/mioScript.php` // aggiungere qua il codice -Assomiglia molto alle prime righe di un front controller (vedere il Capitolo 6), perché queste linee fanno la stessa cosa: inizializzano symfony, analizzano la configurazione del progetto e dell'applicazione. Notare che il metodo `ProjectConfiguration::getApplicationConfiguration` richiede tre parametri: +Assomiglia molto alle prime righe di un front controller (vedere il capitolo 6), perché queste linee fanno la stessa cosa: inizializzano symfony, analizzano la configurazione del progetto e dell'applicazione. Notare che il metodo `ProjectConfiguration::getApplicationConfiguration` richiede tre parametri: * un nome di applicazione * un nome di ambiente @@ -501,7 +501,7 @@ Nella chiamata è possibile specificare un'altra cartella per le fixture. In que Si è imparato come aggiungere record a una singola tabella, ma come si fa ad aggiungere record con chiavi esterne a un'altra tabella? Dal momento che la chiave primaria non è inclusa nei dati delle fixture, c'è bisogno di un modo alternativo per relazionare dei record con altri. -Torniamo all'esempio del Capitolo 8, dove la tabella `blog_article` è collegata alla tabella `blog_comment`, come mostrato in Figura 16-8. +Torniamo all'esempio del capitolo 8, dove la tabella `blog_article` è collegata alla tabella `blog_comment`, come mostrato in Figura 16-8. Figura 16-8 - Esempio di un modello relazionale di database @@ -551,7 +551,7 @@ Symfony offre comandi manuali per sincronizzare due versioni di un sito web. Que ### L'utilizzo di `rsync` per il trasferimento incrementale di file -L'invio della cartella principale di un progetto tramite FTP va bene per il primo trasferimento, ma quando si ha bisogno di caricare un aggiornamento dell'applicazione, in cui sono cambiati solo alcuni file, l'FTP non è l'ideale. È necessario trasferire nuovamente l'intero progetto, il che è uno spreco di tempo e di larghezza di banda. In alternativa si può passare alla directory in cui si sa che alcuni file sono stati modificati e trasferire solo quelli con certe date di modifica. Questo è un lavoro che richiede tempo ed è suscettibile di errori. Inoltre, il sito web può diventare non disponibile o restituire errori durante il tempo del trasferimento. +L'invio della cartella principale di un progetto tramite FTP va bene per il primo trasferimento, ma quando si ha bisogno di caricare un aggiornamento dell'applicazione, in cui sono cambiati solo alcuni file, l'FTP non è l'ideale. È necessario trasferire nuovamente l'intero progetto, il che è uno spreco di tempo e di larghezza di banda. In alternativa si può passare alla cartella in cui si sa che alcuni file sono stati modificati e trasferire solo quelli con certe date di modifica. Questo è un lavoro che richiede tempo ed è suscettibile di errori. Inoltre, il sito web può diventare non disponibile o restituire errori durante il tempo del trasferimento. La soluzione supportata da symfony è la sincronizzazione rsync attraverso SSH. [Rsync] (http://samba.anu.edu.au/rsync/) è una utility a riga di comando che consente il trasferimento incrementale di file in modo veloce ed è open source. Con il trasferimento incrementale, solo i dati modificati verranno inviati. Se un file non è stato modificato, non sarà inviato all'host. Se un file è stato modificato solo in parte, sarà inviata solo la parte cambiata. Il vantaggio principale è che la sincronizzazione con rsync trasferire solo una piccola quantità di dati ed è molto veloce. @@ -598,11 +598,11 @@ Non dimenticarsi di cancellare la cache nel server di produzione dopo la sincron > >Prima di inviare l'applicazione in produzione, bisogna essere sicuri che sia pronta per un utilizzo pubblico. Verificare i punti seguenti prima di decidere di distribuire l'aplicazione: > ->Le pagine degli errori devono essere personalizzate in base al look and feel dell'applicazione. Fare riferimento al Capitolo 19 per vedere come personalizzare l'errore 500, l'errore 404, le pagine messe in sicurezza e alla sezione "Gestire un'applicazione in produzione" di questo capitolo per vedere come personalizzare le pagine visualizzate quando il sito non è disponibile. +>Le pagine degli errori devono essere personalizzate in base al look and feel dell'applicazione. Fare riferimento al capitolo 19 per vedere come personalizzare l'errore 500, l'errore 404, le pagine messe in sicurezza e alla sezione "Gestire un'applicazione in produzione" di questo capitolo per vedere come personalizzare le pagine visualizzate quando il sito non è disponibile. > >Il modulo `default` dovrebbe essere rimosso dall'array `enabled_modules` presente in `settings.yml`, in modo che nessuna pagina di symfony possa comparire per errore. > ->Il meccanismo di gestione della sessione utilizza un cookie lato client e questo cookie in modalità predefinita si chiama `symfony`. Prima di distribuire l'applicazione, si dovrebbe rinominarlo, in modo da evitare la divulgazione del fatto che l'applicazione utilizza symfony. Fare riferimento al Capitolo 6 per vedere come personalizzare il nome del cookie nel file `factories.yml`. +>Il meccanismo di gestione della sessione utilizza un cookie lato client e questo cookie in modalità predefinita si chiama `symfony`. Prima di distribuire l'applicazione, si dovrebbe rinominarlo, in modo da evitare la divulgazione del fatto che l'applicazione utilizza symfony. Fare riferimento al capitolo 6 per vedere come personalizzare il nome del cookie nel file `factories.yml`. > > Il file `robots.txt` che si trova nella cartella `web/` del progetto, in modalità predefinita è vuoto. Si consiglia di personalizzarlo per informare spider web e robot web su quali parti del sito web possono navigare e quali dovrebbero ignorare. Il più delle volte, questo file viene utilizzato per escludere alcune URL dall'indicizzazione; per esempio le pagine di risorse che non hanno bisogno di indicizzazione (come l'archivio dei bug), o gli infiniti URL in cui i robot potrebbero rimanere bloccati. > diff --git a/gentle-introduction/it/17-Extending-Symfony.markdown b/gentle-introduction/it/17-Extending-Symfony.markdown index acad501..ae98d32 100644 --- a/gentle-introduction/it/17-Extending-Symfony.markdown +++ b/gentle-introduction/it/17-Extending-Symfony.markdown @@ -86,7 +86,7 @@ Il metodo `notify()` del dispatcher di eventi si aspetta un oggetto `sfEvent` co ### Notifica di un evento al dispatcher finché un ascoltatore lo prende in carico -Usando il metodo `notify()`, si è sicuri che tutti gli ascoltatori registrati sull'evento da notificare vengono eseguiti. Tuttavia, in alcuni casi è necessario consentire a un ascoltatore di fermare l'evento e prevenire che ulteriori ascoltatori possano fare notifiche su di esso. In questo caso, si dovrebbe usare `notifyUntil()` al posto di `notify()`. Il dispatcher eseguirà tutti gli ascoltatori fino a quando uno di questi ritorna `true` e quindi fermerà la notifica degli eventi. In altre parole, `notifyUntil()` è come un messaggio nello spazio del progetto che dice: "Sto facendo questo. Se qualcuno se ne occupa, allora non lo dirò a nessun altro". Il Listato 17-3 mostra come usare questa tecnica in combinazione con un metodo magico `__call()` per aggiungere metodi a una classe esistente in fase di runtime. +Usando il metodo `notify()`, si è sicuri che tutti gli ascoltatori registrati sull'evento da notificare vengono eseguiti. Tuttavia, in alcuni casi è necessario consentire a un ascoltatore di fermare l'evento e prevenire che ulteriori ascoltatori possano fare notifiche su di esso. In questo caso, si dovrebbe usare `notifyUntil()` al posto di `notify()`. Il dispatcher eseguirà tutti gli ascoltatori fino a quando uno di questi restituisce `true` e quindi fermerà la notifica degli eventi. In altre parole, `notifyUntil()` è come un messaggio nello spazio del progetto che dice: "Sto facendo questo. Se qualcuno se ne occupa, allora non lo dirò a nessun altro". Il Listato 17-3 mostra come usare questa tecnica in combinazione con un metodo magico `__call()` per aggiungere metodi a una classe esistente in fase di runtime. Listato 17-3 - Notifica di un evento finché l'ascoltatore restituisce true diff --git a/gentle-introduction/it/19-Mastering-Symfony-s-Configuration-Files.markdown b/gentle-introduction/it/19-Mastering-Symfony-s-Configuration-Files.markdown index 2f3cce1..0c98e0f 100644 --- a/gentle-introduction/it/19-Mastering-Symfony-s-Configuration-Files.markdown +++ b/gentle-introduction/it/19-Mastering-Symfony-s-Configuration-Files.markdown @@ -36,7 +36,7 @@ definisce quale azione eseguire, a seconda dell'errore: Il valore predefinito è `default/error404`. * `login_module` e `login_action`: Azione richiamata quando un utente non autenticato tenta di accedere a una pagina definita come `secure` in `security.yml` (si veda il - Capitolo 6 per maggiori dettagli). Il valore predefinito è `default/login`. + capitolo 6 per maggiori dettagli). Il valore predefinito è `default/login`. * `secure_module` e `secure_action`: Azione richiamata quando un utente non ha le credenziali necessarie per un'azione. Il valore predefinito è `default/secure`. * `module_disabled_module` e `module_disabled_action`: Azione richiamata quando un @@ -69,7 +69,7 @@ possono trovare queste pagine nella cartella * `error.html.php`: Pagina richiamata quando si verifica un errore interno del server in ambiente di produzione. In altri ambienti (quando debug è impostato a `true`), in caso di errore, symfony mostra l'intera pila di esecuzione con un messaggio di errore - esplicito (si veda il Capitolo 16 per maggiori dettagli). + esplicito (si veda il capitolo 16 per maggiori dettagli). * `unavailable.php`: Pagina richiamata quando un utente richiede una pagina mentre l'applicazione è disabilitata (tramite il task `project:disable`). Viene anche richiamata quando la cache è in fase di pulizia (cioè tra la chiamata al task @@ -101,11 +101,11 @@ Tabella 19-1 - Caratteristiche opzionali configurabili in `settings.yml` Parametro | Descrizione | Valore predefinito ------------------- | ---------------------------------------------- | ------------------ `use_database` | Abilita la gestione del database. Impostare a `false` se non si usa un database. | `true` -`i18n` | Abilita la traduzione dell'interfaccia (si veda il Capitolo 13). Impostare a `true` per applicazioni multi-lingua. | `false` +`i18n` | Abilita la traduzione dell'interfaccia (si veda il capitolo 13). Impostare a `true` per applicazioni multi-lingua. | `false` `logging_enabled` | Abilita il log degli eventi di symfony. Impostare a `false` se si vogliono disabilitare i log. | `true` -`escaping_strategy` | Abilita l'escape dell'output (si veda il Capitolo 7). Impostare a `true` se si vuole l'escape dei dati passati ai template. | `true` -`cache` | Abilita template caching (see Capitolo 12). Impostare a `true` se almeno un modulo include il file `cache.yml`. Il filtro della cache (`sfCacheFilter`) è abilitato. | `false` in sviluppo, `true` in produzione -`web_debug` | Abilita la web debug toolbar per facilitare il debug (si veda il Capitolo 16). Impostare a `true` per mostrare toolbar su ogni pagina. | `true` in sviluppo, `false` in produzione +`escaping_strategy` | Abilita l'escape dell'output (si veda il capitolo 7). Impostare a `true` se si vuole l'escape dei dati passati ai template. | `true` +`cache` | Abilita template caching (see capitolo 12). Impostare a `true` se almeno un modulo include il file `cache.yml`. Il filtro della cache (`sfCacheFilter`) è abilitato. | `false` in sviluppo, `true` in produzione +`web_debug` | Abilita la web debug toolbar per facilitare il debug (si veda il capitolo 16). Impostare a `true` per mostrare toolbar su ogni pagina. | `true` in sviluppo, `false` in produzione `check_symfony_version` | Abilita la verifica della versione di symfony a ogni richiesta. Impostare a `true` per pulire la cache automaticamente dopo un aggiornamento di symfony. Lasciare a `false` se si pulisce la cache a mano dopo un aggiornamento. | `false` `check_lock` | Abilita il sistema di blocco dell'applicazione, attivato dai task `cache:clear` e `project:disable` (vedere la sezione precedente). Impostare a `true` per fare in modo che tutte le richieste ad applicazioni disabilitate siano rinviate alla pagina `sfConfig::get('sf_symfony_lib_dir')/exception/data/unavailable.php`. | `false` `compressed` | Abilita la compressione della risposta in PHP. Impostare a `true` per comprimere il codice HTML in uscita tramite il gestore di compressione di PHP. | `false` @@ -119,7 +119,7 @@ parti. #### Impostazioni dell'escape dell'output Le impostazioni di escape dell'output controllano il modo in cui il template accede alle -variabili (vedere Capitolo 7). Il file `settings.yml` include due impostazioni per questa +variabili (vedere capitolo 7). Il file `settings.yml` include due impostazioni per questa caratteristica: * L'impostazione `escaping_strategy` accetta i valori `true` o `false`. @@ -128,7 +128,7 @@ caratteristica: #### Impostazioni del routing -Le impostazioni del routing (vedere Capitolo 9) sono definite in `factories.yml`, sotto +Le impostazioni del routing (vedere capitolo 9) sono definite in `factories.yml`, sotto la chiave `routing`. Il Listato 19-1 mostra la configurazione predefinita del routing. Listato 19-1 - Impostazioni di configurazione del routing, in `frontend/config/factories.yml` @@ -172,7 +172,7 @@ Listato 19-1 - Impostazioni di configurazione del routing, in `frontend/config/f * Lo schema del routing usa una sua cache, in produzione, per accelerare la conversione tra URL esterni e interni. Per impostazione predefinita, questa cache usa il filesystem, ma si può usare qualsiasi classe di cache, a patto di dichiarare tale - classe e le sue impostazioni nel parametro `cache`. Vedere il Capitolo 15 per la lista + classe e le sue impostazioni nel parametro `cache`. Vedere il capitolo 15 per la lista delle classi disponibili. Per disattivare la cache del routing in produzione, impostare il parametro `debug` a `true`. @@ -198,7 +198,7 @@ Ci sono altri parametri legati al routing, ma questo si trova in `settings.yml`: >funzionano solo abilitando il plugin `sfCompat10`. Le impostazioni di validazione dei form controllano il modo in cui i messaggi di errore -sono mostrati dagli helper `Validation` (vedere Capitolo 10). Questi errori sono inseriti +sono mostrati dagli helper `Validation` (vedere capitolo 10). Questi errori sono inseriti in tag `
` usano `validation_error_ class` come attributo `class` e `validation_error_id_prefix` per costruire l'attributo `id`. I valori predefiniti sono `form_error` e `error_for_`, quindi gli attributi mostrati da una chiamata all'helper @@ -212,7 +212,7 @@ per personalizzare tutti i messaggi di errore. Le impostazioni della cache sono definiti per la maggior parte in `cache.yml`, tranne per due impostazioni in `settings.yml`: `cache` abilita la cache e `etag` abilita la gestione -di ETag sul server (vedere Capitolo 15). Si può anche specificare quale sistema di +di ETag sul server (vedere capitolo 15). Si può anche specificare quale sistema di memorizzazione usare per tutte le cache (della vista, del routing e di i18n) in `factories.yml`. Il Listato 19-2 mostra la configurazione predefinita della cache della vista. @@ -259,7 +259,7 @@ dei file per accelerare, ma la si può cambiare. #### Impostazioni di log -Ci sono due impostazioni di log (vedere Capitolo 16) in `settings.yml`: +Ci sono due impostazioni di log (vedere capitolo 16) in `settings.yml`: * `error_reporting` specifica quali eventi inserire nei log di PHP. La sua impostazione predefinita è `E_PARSE | E_COMPILE_ERROR | E_ERROR | E_CORE_ERROR | E_USER_ERROR` per @@ -281,7 +281,7 @@ percorsi: #### Helper predefiniti Gli helper predefiniti, caricati per ogni template, sono dichiarati nell'impostazione -`standard_helpers` (vedere Capitolo 7). I predefiniti sono i gruppi `Partial` e `Cache`. +`standard_helpers` (vedere capitolo 7). I predefiniti sono i gruppi `Partial` e `Cache`. Se si usano altri gruppi di helper in tutti i template di un'applicazione, aggiungere i loro nomi all'impostazione `standard_helpers` fa risparmiare la dichiarazione ripetuta di `use_helper()` in ogni template. @@ -304,7 +304,7 @@ Definito nell'impostazione `charset`, il valore predefinito (e consigliato) è ` >Aggiungere le proprie impostazioni > >Il file `settings.yml` definisce le impostazioni di symfony per un'applicazione. Come ->discusso nel Capitolo 5, quando si vogliono aggiungere nuovi parametri, il posto migliore +>discusso nel capitolo 5, quando si vogliono aggiungere nuovi parametri, il posto migliore >per farlo è il file `frontend/config/app.yml`. Questo file è anche dipendente >dall'ambiente e le impostazioni che vi sono definite sono disponibili tramite la classe >`sfConfig` col prefisso `app_`. @@ -325,7 +325,7 @@ Definito nell'impostazione `charset`, il valore predefinito (e consigliato) è ` Estendere l'autocaricamento --------------------------- -L'autocaricamento, spiegato brevemente nel Capitolo 2, evita di dover richiedere ogni +L'autocaricamento, spiegato brevemente nel capitolo 2, evita di dover richiedere ogni volta le classi, se sono inserite in cartelle specifiche. Questo vuol dire che si può lasciare che il framework faccia il lavoro per noi, consentendogli di caricare solo le classi necessarie nel momento opportuno e solo quando necessario. @@ -429,7 +429,7 @@ metodo di autocaricamento di symfony (e usa i posti definiti in `autoload.yml`). trova una definizione di classe, tutti gli altri callable registrati con `spl_autoload_register()` saranno richiamati, finché la classe non viene trovata. Quindi si possono aggiungere quanti meccanismi di autocaricamento si vuole, ad esempio per -fornire sistemi di aggancio con componenti di altri framework (vedere Capitolo 17). +fornire sistemi di aggancio con componenti di altri framework (vedere capitolo 17). Struttura dei file personalizzata --------------------------------- diff --git a/gentle-introduction/it/A-Inside-the-Model-Layer-Propel.markdown b/gentle-introduction/it/A-Inside-the-Model-Layer-Propel.markdown index 92481f6..d8469dc 100644 --- a/gentle-introduction/it/A-Inside-the-Model-Layer-Propel.markdown +++ b/gentle-introduction/it/A-Inside-the-Model-Layer-Propel.markdown @@ -8,7 +8,7 @@ Questo capitolo spiega come creare un modello di dati a oggetti e come accedere Perché usare un ORM e un livello per l'astrazione? -------------------------------------------------- -I database sono relazionali. PHP 5 e symfony sono orientati agli oggetti. Per poter accedere nel modo più efficace al database in un contesto orientato agli oggetti, è indispensabile una interfaccia per tradurre la logica degli oggetti nella logica relazionale. Come spiegato nel capitolo 1, questa interfaccia è chiamata Object-Relational Mapping (ORM) ed è costituita di oggetti che forniscono l'accesso ai dati e mantengono le business rules all'interno di se stessi. +I database sono relazionali. PHP 5 e symfony sono orientati agli oggetti. Per poter accedere nel modo più efficace al database in un contesto orientato agli oggetti, è indispensabile una interfaccia per tradurre la logica degli oggetti nella logica relazionale. Come spiegato nel capitolo 1, questa interfaccia è chiamata Object-Relational Mapping (ORM), ed è costituita di oggetti che forniscono l'accesso ai dati e mantengono le business rules all'interno di se stessi. Il vantaggio principale di un ORM è la riusabilità, che consente ai metodi di un oggetto di tipo dato, di essere chiamato da varie parti dell'applicazione, anche da diverse applicazioni. Il livello ORM incapsula anche la logica dei dati, ad esempio, il calcolo del punteggio degli utenti di un forum basato su quanti contributi sono stati fatti e quanto sono popolari. Quando una pagina deve visualizzare un tale punteggio degli utenti, basta chiamare semplicemente un metodo nel modello dei dati, senza preoccuparsi dei dettagli del calcolo. Se in seguito bisogna modificare il calcolo, sarà sufficiente modificare il metodo nel modello, lasciando il resto dell'applicazione invariata. @@ -48,7 +48,7 @@ Symfony usa Propel o Doctrine come ORM, e questi usano oggetti PHP per l'astrazi >In un progetto symfony, tutte le applicazioni condividono lo stesso modello. Questo è un punto fondamentale a livello di progetto: raggruppare le applicazioni che si basano su regole di business comuni. Questa è la ragione per cui il modello è indipendente dalle applicazioni e i file del modello sono memorizzati in una cartella `lib/model/` nella radice del progetto. Lo schema del database di symfony -------------------------- +--------------------------------- Allo scopo di creare il modello a oggetti dei dati che symfony userà, bisogna tradurre tutti i modelli relazionali del database in un modello dati a oggetti. L'ORM ha bisogno di una descrizione del modello relazionale per fare la mappatura e questo è chiamato schema. In uno schema si definiscono le tabelle, le relazioni e le caratteristiche delle colonne. @@ -99,18 +99,18 @@ Una tabella può avere attributi speciali, incluso `phpName` (il nome della clas Una tabella contiene colonne. Il valore delle colonne può essere definito in tre differenti modi: - * Se non definisci nulla (`~` in YAML equivale a `null` in PHP), symfony indovinerà i migliori attributi in base al nome della colonna e alcune convenzioni che saranno descritte nella sezione "Colonne vuote" più avanti in questo capitolo. Per esempio, la colonna `id` nel Listato 8-3 non ha bisogno di essere definita: Symfony la renderà un intero auto incrementale, chiave primaria della tabella. La colonna `blog_article_id` nella tabella `blog_comment` sarà capita come una chiave esterna verso la tabella `blog_article` (le colonne che terminano con `_id` sono considerate chiave esterne, e la tabella collegata è determinata automaticamente a seconda della prima parte del nome della colonna). Le colonne chiamate `created_at` sono automaticamente impostate al tipo `timestamp`. Per queste colonne, non devi specificare nessun tipo. Questo è il motivo per cui `schema.yml` è così semplice da scrivere. + * Se non definisci nulla (`~` in YAML equivale a `null` in PHP), symfony indovinerà i migliori attributi in base al nome della colonna e alcune convenzioni che saranno descritte nella sezione "Colonne vuote" più avanti in questo capitolo. Per esempio, la colonna `id` nel Listato 8-3 non ha bisogno di essere definita: Symfony la renderà un intero auto incrementale, chiave primaria della tabella. La colonna `blog_article_id` nella tabella `blog_comment` sarà capita come una chiave esterna verso la tabella `blog_article` (le colonne che terminano con `_id` sono considerate chiave esterne, e la tabella collegata è determinata automaticamente a seconda della prima parte del nome della colonna). Le colonne chiamate `created_at` sono automaticamente impostate al tipo `timestamp`. Per queste colonne, non occorre specificare nessun tipo. Questo è il motivo per cui `schema.yml` è così semplice da scrivere. - * Se definisci soltanto un attributo, questo sarà il tipo della colonna. Symfony conosce i classici tipi: `boolean`, `integer`, `float`, `date`, `varchar(lunghezza)`, `longvarchar` (convertito, per esempio, a `text` in MySQL), e così via. Per stringhe superiori ai 256 caratteri devi usare il valore `longvarchar` che non ha lunghezza (ma non può eccedere 65KB in MySQL). + * Se definisci soltanto un attributo, questo sarà il tipo della colonna. Symfony conosce i classici tipi: `boolean`, `integer`, `float`, `date`, `varchar(lunghezza)`, `longvarchar` (convertito, per esempio, a `text` in MySQL), e così via. Per stringhe superiori ai 256 caratteri occorre usare il valore `longvarchar`, che non ha lunghezza (ma non può eccedere 65KB in MySQL). - * Se hai bisogno di definire altri attributi (come il valore di default, se il campo è obbligatorio, e così via), dovresti scrivere gli attributi della colonna come un insieme di `chiave: valore`. Questa sintassi estesa è spiegata più avanti nel capitolo. + * Se occorre definire altri attributi (come il valore di default, se il campo è obbligatorio, e così via), si dovrebbero scrivere gli attributi della colonna come un insieme di `chiave: valore`. Questa sintassi estesa è spiegata più avanti nel capitolo. Le colonne possono avere un attributi `phpName`, che è la versione con prima lettera maiuscola del nome (`Id`, `Title`, `Content`, e così via) e non ha bisogno di essere specificata nella maggior parte dei casi. Le tabelle possono inoltre contenere esplicite chiavi esterne e indici, come anche alcune definizioni specifiche per alcuni database. Controlla la sezione `Sintassi estesa dello schema` più avanti in questo capitolo per saperne di più. Le classi del modello -------------- +--------------------- Lo schema è usato per costruire le classi del modello nel livello ORM. Per risparmiare tempo di esecuzione, queste classi sono generate con un task a riga di comando chiamato `propel:build-model`. $ php symfony propel:build-model @@ -146,7 +146,7 @@ D'altra parte, le classi di oggetti personalizzati presenti nella cartella `lib/ Il Listato 8-4 mostra un esempio di una classe personalizzata del modello, così come viene creata dopo la prima chiamata del task `propel:build-model`. -Listing 8-4 - Esempio di file di una classe del modello, in `lib/model/Article.php` +Listato 8-4 - Esempio di file di una classe del modello, in `lib/model/Article.php` [php] class Article extends BaseArticle @@ -168,7 +168,7 @@ Listato 8-5 - Getter per colonne dei record sono disponibili nelle classi oggett // ... $title = $article->getTitle(); -`ArticlePeer` e `CommentPeer` sono classi peer; ovvero, classi che contengono metodi statici che operano sulle tabelle. Possono fornire un modo per recuperare righe dalle tabelle. I loro metodi ritornano solitamente un oggetto o collezione di oggetti della collegata classe oggetto, come mostrato nel Listato 8-6. +`ArticlePeer` e `CommentPeer` sono classi peer; ovvero, classi che contengono metodi statici che operano sulle tabelle. Possono fornire un modo per recuperare righe dalle tabelle. I loro metodi restituiscono solitamente un oggetto o collezione di oggetti della collegata classe oggetto, come mostrato nel Listato 8-6. Listato 8-6 - Metodi statici per recuperare record sono disponibili nelle classi peer @@ -179,7 +179,7 @@ Listato 8-6 - Metodi statici per recuperare record sono disponibili nelle classi >**NOTE** >Da un punto di vista di modello di dati, non potrebbe esserci un oggetto peer. Per questo che i metodi delle classi peer sono chiamati con `::` (operatore per metodi statici), al posto del solito `->` (per le chiamate a metodi d'istanza). -Per questo combinare classi oggetto e peer, base e personalizzate risulta in quattro classi generate per ogni tabella descritta nello schema. A dir la verità, c'è una quinta classe creata nella directory `lib/model/map/`, che contiene metadati riguardo le tabelle ed è necessaria per l'ambiente di esecuzione. Ma dato che probabilmente non si avrà mai a che fare con questa classe, ce ne si può tranquillamente dimenticare. +Per questo combinare classi oggetto e peer, base e personalizzate risulta in quattro classi generate per ogni tabella descritta nello schema. A dir la verità, c'è una quinta classe creata nella cartella `lib/model/map/`, che contiene metadati riguardo le tabelle ed è necessaria per l'ambiente di esecuzione. Ma dato che probabilmente non si avrà mai a che fare con questa classe, ce ne si può tranquillamente dimenticare. Accesso ai dati --------------- @@ -211,7 +211,7 @@ Listato 8-7 - Metodi generati nella classe dell'oggetto >**NOTE** >La classe oggetto generata si chiama `Article`, che è il `phpName` dato alla tabella `blog_article`. Se `phpName` non è stato definito nello schema, la classe sarebbe stata chiamata `BlogArticle`. Gli accessori e modificatori usano una variante camelCase del nome delle colonne, quindi il metodo `getTitle()` resituirà il valore della colonna `title`. -Impostare diversi valori in un unica volta, si può usare il metodo `fromArray()`, generato per ogni classe oggetto, come mostrato nel Listato 8-8. +Per impostare diversi valori in una sola volta, si può usare il metodo `fromArray()`, generato per ogni classe oggetto, come mostrato nel Listato 8-8. Listato 8-8 - Il metodo `fromArray()` è un setter multiplo @@ -265,7 +265,7 @@ Listato 8-10 - Chiavi esterne sono trasformate in speciali getter // Relazione uno-a-molti $comments = $article->getComments(); -Il metodo `getArticle()` ritorna un oggetto di classe `Article`, con i benefici del metodo accessore `getTitle()`. Questo è molto migliore di dover eseguire la join tu stesso, che potrebbe richiedere alcune linee di codice (a partire dalla riga `$comment->getArticleId()`). +Il metodo `getArticle()` restituisce un oggetto di classe `Article`, con i benefici del metodo accessore `getTitle()`. Questo è molto migliore di dover eseguire la join tu stesso, che potrebbe richiedere alcune linee di codice (a partire dalla riga `$comment->getArticleId()`). La variabile `$comments` nel listato 8-10 contiene un array di oggetti di classe `Comment`. Si può mostrare il primo con `$comments[0]` o iterare sulla collezione con `foreach ($comments as $comment)`. @@ -274,7 +274,7 @@ La variabile `$comments` nel listato 8-10 contiene un array di oggetti di classe ### Salvare ed eliminare dati -Chiamando il costruttore con `new`, hai creato un nuovo oggetto, ma non un record nella tabella `blog_article`. Nemmeno modificare l'oggetto ha effetto sul database. Per salvare dati nel database, devi chiamare il metodo `save()` sull'oggetto. +Chiamando il costruttore con `new`, un nuovo oggetto è stato creato, ma non un record nella tabella `blog_article`. Nemmeno modificare l'oggetto ha effetto sul database. Per salvare dati nel database, occorre chiamare il metodo `save()` sull'oggetto. [php] $article->save(); @@ -297,14 +297,14 @@ Listato 8-11 - Cancellare righe dal database con il metodo `delete()` dell'ogget >**TIP** >Anche dopo aver chiamato il metodo `delete()`, un oggetto rimane disponibile fino alla fine dell'esecuzione. Per determinare se un oggetto è stato cancellato dal database, chiama il metodo `isDeleted()`. -### Recuperare record usando la chiave primaria +### Recuperare record tramite chiave primaria -Se conosci la chiave primaria di un particolare record, usa il metodo `retrieveByPk()` della classe peer per ottenere il relativo oggetto. +Se si conosce la chiave primaria di un certo record, usare il metodo `retrieveByPk()` della classe peer per ottenere il relativo oggetto. [php] $article = ArticlePeer::retrieveByPk(7); -Il file `schema.yml` definisce il campo `id` come la chiave primaria della tabella `blog_article`, quindi questo comando ritornerà un articolo che ha `id` uguale a 7. Dato che hai utilizzato la chiave primaria, sai che soltanto un record sarà ritornato; la variabile `$article` contiene un oggetto della classe `Article`. +Il file `schema.yml` definisce il campo `id` come la chiave primaria della tabella `blog_article`, quindi questo comando restituisce un articolo che ha `id` uguale a 7. Dato che è stata usata la chiave primaria, sappiamo che soltanto un record sarà restituito; la variabile `$article` contiene un oggetto della classe `Article`. In alcuni casi, una chiave primaria può consistere in più di una colonna. In questi casi, il metodo `retrieveByPk()` accetta parametri multipli, uno per ogni colonna della chiave primaria. @@ -316,7 +316,7 @@ Quando si vuole recuperare più di un record, occorre utilizzare il metodo `doSe Il primo parametro del metodo `doSelect()` è un oggetto della classe `Criteria`, che è una semplice classe per la costruzione delle query, senza l'utilizzo di SQL per mantenere l'astrazione dal database. -Un oggetto `Criteria` vuoto ritorna tutti gli oggetti della classe. Per esempio, il codice mostrato nel Listato 8-12 ritorna tutti gli articoli. +Un oggetto `Criteria` vuoto restituisce tutti gli oggetti della classe. Per esempio, il codice mostrato nel Listato 8-12 restituisce tutti gli articoli. Listato 8-12 - Recuperare record usando Criteria e `doSelect()`--Criteria vuoto @@ -332,7 +332,7 @@ Listato 8-12 - Recuperare record usando Criteria e `doSelect()`--Criteria vuoto >**SIDEBAR** >Idratazione > ->La chiamata a `::doSelect()` è a dir la verità molto più potente di una semplice query SQL. Per prima cosa, il codice SQL generato è ottimizzato per il DBMS scelto. Secondo, su ogni valore passato a `Criteria` viene effettuato l'escape prima di venir intergrato nel codice SQL, che previene rischi di SQL injection. Terzo, questo metodo ritorna un array di oggetti piuttosto che una risorsa PHP. L'ORM crea automaticamente gli oggetti basandosi sulla risorsa ritornata dal database. Questo processo è chiamato idratazione. +>La chiamata a `::doSelect()` è a dir la verità molto più potente di una semplice query SQL. Per prima cosa, il codice SQL generato è ottimizzato per il DBMS scelto. Secondo, su ogni valore passato a `Criteria` viene effettuato l'escape prima di venir intergrato nel codice SQL, che previene rischi di SQL injection. Terzo, questo metodo restituisce un array di oggetti piuttosto che una risorsa PHP. L'ORM crea automaticamente gli oggetti basandosi sulla risorsa restituita dal database. Questo processo è chiamato idratazione. Per una selezione più complessa, avrai bisogno degli equivalenti di WHERE, ORDER BY, GROUP BY e altre istruzioni SQL. L'oggetto `Criteria` ha metodi e parametri per tutte queste condizioni. Per esempio, per ottenere tutti i commenti scritti da Steve, ordinati per data, costruisci un `Criteria` come mostrato nel Listato 8-13. @@ -354,7 +354,7 @@ Listato 8-13 - Recuperare record usando Criteria e `doSelect()`--Criteria con co Le costanti di classe passate come parametri dei metodi `add()` si riferiscono ai nomi delle propietà. Sono chiamate con la versione maiuscola dei nomi delle colonne. Per esempio, per la colonna `content` della tabella `blog_article`, usa la costante `ArticlePeer::CONTENT`. >**NOTE** ->Perché usare `CommentPeer::AUTHOR` al posto di `blog_comment.AUTHOR`, che è quello che sarà utilizzato nel codice SQL in ogni caso? Supponi di dover cambiare il nome della colonna da `author` a `contributor` nel database. Se tu avessi usato `blog_comment.AUTHOR`, dovresti cambiarlo a ogni chiamata del metodo. Invece, usando `CommentPeer::AUTHOR`, devi soltanto cambiare il nome della colonna nel file `schema.yml`, impostare il valore `phpName` ad `AUTHOR` e ricostruire il modello. +>Perché usare `CommentPeer::AUTHOR` al posto di `blog_comment.AUTHOR`, che è quello che sarà utilizzato nel codice SQL in ogni caso? Supponi di dover cambiare il nome della colonna da `author` a `contributor` nel database. Se tu avessi usato `blog_comment.AUTHOR`, dovresti cambiarlo a ogni chiamata del metodo. Invece, usando `CommentPeer::AUTHOR`, occorre soltanto cambiare il nome della colonna nel file `schema.yml`, impostare il valore `phpName` ad `AUTHOR` e ricostruire il modello. La Tabella 8-1 confronta la sintassi SQL con quella della classe `Criteria`. @@ -380,11 +380,11 @@ SQL | Criteria `FROM table1 RIGHT JOIN table2 ON table1.col1 = table2.col2` | `->addJoin(col1, col2, Criteria::RIGHT_JOIN)` >**TIP** ->Il modo migliore per scoprire e capire quali metodi sono disponibili nelle classi generate è guardare ai file `Base` nella cartella `lib/model/om/` dopo la generazione. I nomi dei metodi sono abbastanza espliciti, ma se hai bisogno di commenti in essi imposta il parametro `propel.builder.addComments` a `true` nel file `config/propel.ini` e ricostruisci il modello. +>Il modo migliore per scoprire e capire quali metodi sono disponibili nelle classi generate è guardare ai file `Base` nella cartella `lib/model/om/` dopo la generazione. I nomi dei metodi sono abbastanza espliciti, ma se servono dei commenti in essi si può impostare il parametro `propel.builder.addComments` a `true` nel file `config/propel.ini` e ricostruire il modello. Il Listato 8-14 mostra un altro esempio di `Criteria` con condizioni multiple. Recupera tutti i commenti di Steve sugli articoli contenenti la parola "enjoy", ordinati per data. -Listato 8-14 - Un altro esempio di recuperato record con Criteria e `doSelect()`--Criteria con condizioni +Listato 8-14 - Un altro esempio di record recuperato con Criteria e `doSelect()`--Criteria con condizioni [php] $c = new Criteria(); @@ -405,29 +405,29 @@ Listato 8-14 - Un altro esempio di recuperato record con Criteria e `doSelect()` Come SQL è un linguaggio semplice che consente di gestire interrogazioni molto complesse, l'oggetto Criteria può gestire condizioni con ogni livello di complessità. Ma dato che molti sviluppatori pensano in SQL prima di tradurre una condizione in logica object-oriented, l'oggetto `Criteria` può essere difficile da comprendere all'inizio. Il miglior modo di capirlo è imparare dagli esempi e applicazioni esistenti. Il sito di symfony, per esempio, è pieno di esempi di utilizzo di `Criteria` che ti aiuteranno in molte situazioni. -In aggiunta al metodo `doSelect()`, ogni classe peer ha un metodo `doCount()`, che semplicemente ritorna il numero di record che soddisfano i requisiti passati come parametri e ritorna un numero intero. Dato che nessun oggetto viene ritornato, il processo di idratazione non viene eseguito in questo caso, perciò il metodo `doCount()` è più veloce di `doSelect()`. +In aggiunta al metodo `doSelect()`, ogni classe peer ha un metodo `doCount()`, che semplicemente restituiscono il numero di record che soddisfano i requisiti passati come parametri e restituisce un numero intero. Dato che nessun oggetto viene restituito, il processo di idratazione non viene eseguito in questo caso, perciò il metodo `doCount()` è più veloce di `doSelect()`. -La classi peer forniscono inoltre i metodi `doDelete()`, `doInsert()` e `doUpdate()`, che ricevono un oggetto `Criteria` come parametro. Questi metodi consentono di eseguire interrogazioni di tipo `DELETE`, `INSERT` e `UPDATE` sul database. Dai un'occhiata alle classi peer generate nel tuo modello per ulteriori dettagli su questi metodi di Propel. +La classi peer forniscono inoltre i metodi `doDelete()`, `doInsert()` e `doUpdate()`, che ricevono un oggetto `Criteria` come parametro. Questi metodi consentono di eseguire interrogazioni di tipo `DELETE`, `INSERT` e `UPDATE` sul database. Dare un'occhiata alle classi peer generate nel modello per ulteriori dettagli su questi metodi di Propel. -Infine, se si vuole soltanto il primo oggetto, sostituire `doSelect()` con `doSelectOne()`. Questo potrebbe essere il caso in cui si sa che `Criteria` produrrà un risultato soltanto, con il vantaggio che il metodo ritornerà direttamente un oggetto piuttosto di un array. +Infine, se si vuole soltanto il primo oggetto, sostituire `doSelect()` con `doSelectOne()`. Questo potrebbe essere il caso in cui si sa che `Criteria` produrrà un risultato soltanto, con il vantaggio che il metodo restuituirà direttamente un oggetto piuttosto di un array. >**TIP** ->Quando una query ritorna un gran numero di risultati, potresti volerne mostrare soltanto un sottoinsieme. Symfony fornisce una classe per la suddivisione in pagine chiamata `sfPropelPager`, che automatizza la paginazione dei risultati. +>Quando una query restituisce un gran numero di risultati, si potrebbe volerne mostrare soltanto un sottoinsieme. Symfony fornisce una classe per la suddivisione in pagine chiamata `sfPropelPager`, che automatizza la paginazione dei risultati. ### Usare query SQL -A volte, non ti serve recuperare oggetti, ma vuoi soltanto risultati sintetici calcolati dal database. Per esempio, per ottenere l'ultima data di creazione di tutti gli articoli, non ha senso recuperare tutti gli articoli ed eseguire un ciclo sull'array. È preferibile richiedere direttamente al database di ritornare soltanto il risultato, perché salterà il processo di idratazione. +A volte non serve recuperare oggetti, ma soltanto avere risultati sintetici calcolati dal database. Per esempio, per ottenere l'ultima data di creazione di tutti gli articoli, non ha senso recuperare tutti gli articoli ed eseguire un ciclo sull'array. È preferibile richiedere direttamente al database di restituire soltanto il risultato, perché salterà il processo di idratazione. -D'altra parte, non è il caso di usare i comandi PHP per gestire direttamente il database, perché perderesti i vantaggi dell'astrazione dal database. Questo significa che hai bisogno di bypassare l'ORM (Propel) ma non l'astrazione dal database (PDO). +D'altra parte, non è il caso di usare i comandi PHP per gestire direttamente il database, perché perderesti i vantaggi dell'astrazione dal database. Questo significa che occorre aggirare l'ORM (Propel) ma non l'astrazione dal database (PDO). -Una query al database con PHP Data Objects richiede che tu faccia il seguente: +Una query al database con PHP Data Objects richiede i seguentii passi: - 1. Ottieni una connessione al database - 2. Crea una query - 3. Usala per creare uno "statement" - 4. Cicla sul risultato dell'esecuzione dello statement + 1. Ottienre una connessione al database + 2. Creare una query + 3. Usarla per creare uno "statement" + 4. Ciclare sul risultato dell'esecuzione dello statement -Se queste sembrano parole campate in aria per te, il codice del Listato 8-15 probabilmente sarà più esplicito. +Se queste sembrano parole campate in aria, il codice del Listato 8-15 probabilmente sarà più esplicito. Listato 8-15 - Query SQL personalizzata con PDO @@ -441,16 +441,16 @@ Listato 8-15 - Query SQL personalizzata con PDO $resultset = $statement->fetch(PDO::FETCH_OBJ); $max = $resultset->max; -Proprio come le selezioni con Propel, le query con PDO sono complesse la prima volta che inizi ad usarle. Ma anche stavolta, esempi da applicazioni esistenti e tutorial ti mostreranno il modo giusto. +Proprio come le selezioni con Propel, le query con PDO sono complesse quando si inizia a usarle. Ma anche stavolta, esempi da applicazioni esistenti e tutorial mostreranno il modo giusto. >**CAUTION** ->Se sei tentato di bypassare questo processo ed accedere al database direttamente, rischi di perdere la sicurezza ed astrazione fornita da Propel. Facendo in questo modo, ma ti forza ad usare le migliori pratiche per garantire performance, portabilità, e sicurezza della tua applicazione. Questo è specialmente vero per query che contengono parametri che arrivano da una fonte non sicura (come ad esempio l'utente). Propel fa tutto il lavoro necessario per mettere al sicuro il tuo database. Accedere al database dirttamente ti mette a rischio di attacchi di tipo SQL-injection. +>Se si è tentati di aggirare questo processo e accedere al database direttamente, si rischia di perdere la sicurezza e l'astrazione fornite da Propel. Facendo in questo modo si impiega di più, ma costinge a usare le migliori pratiche per garantire prestazioni, portabilità e sicurezza della propria applicazione. Questo è vero specialmente per query che contengono parametri che arrivano da una fonte non sicura (come ad esempio l'utente). Propel fa tutto il lavoro necessario per mettere al sicuro il database. Accedere al database dirttamente mette a rischio di attacchi di tipo SQL-injection. -### Usare colonne di tipo data speciali +### Uso di colonne speciali per le date Di solito, quando una tabella ha una colonna chiamata `created_at`, è usata per salvare il timestamp della data di quando il record è stato creato. Lo stesso succede per le colonne `updated_at`, che saranno aggiornate ogni volta che il record stesso viene aggiornato. -La buona notizia è che symfony riconoscerà i nomi di queste colonne e gestirà il loro aggiornamento per te. Non avrai bisogno di impostare manualmente i valori di `created_at` e `updated_at`; saranno aggiornati automaticamente, come mostrato nel Listato 8-16. Lo stesso succede per le colonne chiamate `created_on` e `updated_on`. +La buona notizia è che symfony riconoscerà i nomi di queste colonne e gestirà il loro autonomamente. Non servirò impostare manualmente i valori di `created_at` e `updated_at`, saranno aggiornati automaticamente, come mostrato nel Listato 8-16. Lo stesso succede per le colonne chiamate `created_on` e `updated_on`. Listato 8-16 - Le colonne `created_at` e `updated_at` sono gestite in automatico @@ -469,11 +469,11 @@ Inoltre, il getter per le colonne di tipo data accetta un formato di data come p echo $comment->getCreatedAt('Y-m-d'); >**SIDEBAR** ->Refactoring dello strato di gestione dei dati +>Rifattorizzazione del livello di gestione dei dati > ->Durante lo sviluppo di un progetto symfony, inizierai spesso scrivendo il codice per le azioni sul database nelle azioni. Ma le query al database e manipolazione del modello non dovrebbero risiedere nello strato del controller. Per questo, tutto il codice per la gestione del database dovrebbe essere spostato nel modello. Nel caso avessi bisogno di fare la stessa richiesta al database in più di un punto nelle tue azioni, pensa al trasferire il relativo codice nel modello. Aiuta a tenere le azioni corte e leggibili. +>Durante lo sviluppo di un progetto symfony, si inizia spesso scrivendo il codice per il database nelle azioni. Ma le query al database e manipolazione del modello non dovrebbero risiedere nel livello del controllore. Per questo, tutto il codice per la gestione del database dovrebbe essere spostato nel modello. Nel caso occorra fare la stessa richiesta al database in più di un punto nelle azioni, si dovrebbe trasferire il relativo codice nel modello. Aiuta a tenere le azioni corte e leggibili. > ->Per esempio, immagina il codice in un blog per recuperare i dieci articoli più popolari per un determinato tag (passato come parametro della richiesta). Questo codice non dovrebbe risiedere nell'azione, ma nel modello. Infatti, se avrai bisogno di mostrare questa lista in un template, l'azione dovrebbe essere così semplice: +>Per esempio, si immagini il codice in un blog per recuperare i dieci articoli più popolari per un determinato tag (passato come parametro della richiesta). Questo codice non dovrebbe risiedere nell'azione, ma nel modello. Infatti, se si avrà bisogno di mostrare questa lista in un template, l'azione dovrebbe essere così semplice: > > [php] > public function executeShowPopularArticlesForTag($request) @@ -483,30 +483,30 @@ Inoltre, il getter per le colonne di tipo data accetta un formato di data come p > $this->articles = $tag->getPopularArticles(10); > } > ->L'azione crea un oggetto della classe `Tag` dal parametro di richiesta. Poi, tutto il codice necessario alla query al database è localizzato nel metodo `getPopularArticles()` di questa classe. Rende l'azione più leggibile, ed il codice può essere facilmente riutilizzato in un'altra azione. +>L'azione crea un oggetto della classe `Tag` dal parametro di richiesta. Poi, tutto il codice necessario alla query al database è localizzato nel metodo `getPopularArticles()` di questa classe. Rende l'azione più leggibile e il codice può essere facilmente riutilizzato in un'altra azione. > ->Spostare il codice nel posto più appropriato è una delle tecniche del refactoring. Se lo fai spesso, il tuo codice sarà facilmente mantenibile e comprensibile da altri sviluppatori. Una buona convenzione sul quando fare refactoring verso il modello consiste nel riuscire a mantenere un numero di righe di codice di un azione inferiore a dieci. +>Spostare il codice nel posto più appropriato è una delle tecniche della rifattorizzazione. Se lo si fa spesso, il proprio codice sarà facilmente mantenibile e comprensibile da altri sviluppatori. Una buona convenzione sul quando rifattorizzare verso il modello consiste nel riuscire a mantenere un numero di righe di codice di un azione inferiore a dieci. Connessioni al database --------------------- +----------------------- -Il modello è indipendente dal database usato, ma per forza di cose userai un database. Le informazioni minime richiesta da symfony per inviare richieste al database è il nome, le credenziali di acecsso ed il tipo di database. Queste impostazioni di connessione possono essere configurati passato un data source name (DSN) al processo `configure:database`: +Il modello è indipendente dal database usato, ma per forza di cose si userà un database. Le informazioni minime richiesta da symfony per inviare richieste al database sono il nome, le credenziali di accesso e il tipo di database. Queste impostazioni di connessione possono essere configurati passando un data source name (DSN) al task `configure:database`: $ php symfony configure:database "mysql:host=localhost;dbname=blog" root mYsEcret -Le impostazioni di connessione dipendono dall'ambiente di lavoro. Puoi definire configurazioni differenti per gli ambienti `prod`, `dev` e `test`, o per ogni altro ambiente nella tua applicazione usando l'opzione `env`: +Le impostazioni di connessione dipendono dall'ambiente. Si possono definire configurazioni differenti per gli ambienti `prod`, `dev` e `test`, o per ogni altro ambiente nella propria applicazione usando l'opzione `env`: $ php symfony configure:database --env=dev "mysql:host=localhost;dbname=blog_dev" root mYsEcret -Questa configurazione può inoltre venir sovrascritta per ogni applicazione. Per esempio, puoi usare questo approccio per avere differenti polizze di sicurezza per le tue applicazioni frontend o backend, e definire utenti del database differenti con privilegi diversi per gestire tutto ciò: +Questa configurazione può inoltre venir sovrascritta per ogni applicazione. Per esempio, si può usare questo approccio per avere differenti polizze di sicurezza per le tue applicazioni frontend o backend, e definire utenti del database differenti con privilegi diversi per gestire tutto ciò: $ php symfony configure:database --app=frontend "mysql:host=localhost;dbname=blog" root mYsEcret -Per ogni ambiente, puoi definire differenti connessioni. Ogni connessione si riferisce allo schema chiamato con lo stesso nome. La connessione di default si chiama `propel` e si riferisce allo schema `propel` nel Listato 8-3. L'opzione `name` consente di creare un altra connessione: +Per ogni ambiente, si possono definire differenti connessioni. Ogni connessione si riferisce allo schema chiamato con lo stesso nome. La connessione predefinita si chiama `propel` e si riferisce allo schema `propel` nel Listato 8-3. L'opzione `name` consente di creare un altra connessione: $ php symfony configure:database --name=main "mysql:host=localhost;dbname=example" root mYsEcret -Puoi inoltre inserire queste impostazioni di connessione manualmente nel file `databases.yml` collocato nella cartella `config/`. Il Listato 8-17 mostra un esempio di questo file ed il Listato 8-18 mostra lo stesso esempio con la notazione estesa. +Si possono inoltre inserire queste impostazioni di connessione manualmente nel file `databases.yml` collocato nella cartella `config/`. Il Listato 8-17 mostra un esempio di questo file e il Listato 8-18 mostra lo stesso esempio con la notazione estesa. Listato 8-17 - Notazione semplice per la connessione al database @@ -552,7 +552,7 @@ I valori consentiti per il parametri `phptype` sono quelli dei database supporta Per sovrascrivere la configurazione per applicazione, avrai bisogno di modificare il file specifico dell'applicazione, come `apps/frontend/config/databases.yml`. -Se usi un database SQLite, il parametro `hostspec` deve essere impostato al percorso del file del database. Per esempio, se tu tieni il tuo blog in `data/blog.db`, il file `databases.yml` sarà come quello nel Listato 8-19. +Se usi un database SQLite, il parametro `hostspec` deve essere impostato al percorso del file del database. Per esempio, se si tieni il proprio blog in `data/blog.db`, il file `databases.yml` sarà come quello nel Listato 8-19. Listato 8-19 - Connessione al database specifica per SQLite usando un percorso file come host @@ -565,15 +565,15 @@ Listato 8-19 - Connessione al database specifica per SQLite usando un percorso f database: %SF_DATA_DIR%/blog.db Estendere il modello -------------------- +-------------------- -I metodi generati del modello sono ottimi, ma spesso non sufficienti. Presto implementerai la tua logica ed avrai bisogno di estenderlo, aggiungendo nuovi metodi oppure sovrascrivendo quelli esistenti. +I metodi generati del modello sono ottimi, ma spesso non sufficienti. Al momento di implementare la logica, si avrà bisogno di estenderlo, aggiungendo nuovi metodi oppure sovrascrivendo quelli esistenti. ### Aggiungere nuovi metodi -Puoi aggiugnere nuovi metodi alle classi del modello vuote generate nella cartella `lib/model`. Usa `$this` per chiamare metodi sull'oggetto corrente, mentre usa `self::` per chiamare metodi statici sulla classe corrente. Ricorda che le classi personalizzate ereditano i metodi dalle classi `Base` collocate nella cartella `lib/model/om`. +Si possono aggiungere nuovi metodi alle classi del modello vuote generate nella cartella `lib/model`. Usare `$this` per chiamare metodi sull'oggetto corrente e usare `self::` per chiamare metodi statici sulla classe corrente. Si ricordi che le classi personalizzate ereditano i metodi dalle classi `Base` collocate nella cartella `lib/model/om`. -Per esempio, per l'oggetto `Article` generato basato sul Listato 8-3, puoi aggiungere un metodo magico `__toString()` per far si che un comando `echo` su un oggetto di classe `Article` mostri il suo titolo, come mostrato nel Listato 8-20. +Per esempio, per l'oggetto `Article` generato basato sul Listato 8-3, si può aggiungere un metodo magico `__toString()` per far sì che un comando `echo` su un oggetto di classe `Article` mostri il suo titolo, come mostrato nel Listato 8-20. Listato 8-20 - Personalizzazione del modello, in `lib/model/Article.php` @@ -586,7 +586,7 @@ Listato 8-20 - Personalizzazione del modello, in `lib/model/Article.php` } } -Puoi inoltre estendere le classi peer, per esempio, per aggiungere un metodo per recuperare tutti gli articoli ordinati per data di creazione, come mostrato nel Listato 8-21. +Si possono inoltre estendere le classi peer, per esempio, per aggiungere un metodo per recuperare tutti gli articoli ordinati per data di creazione, come mostrato nel Listato 8-21. Listato 8-21 - Personalizzazione del modello, in `lib/model/ArticlePeer.php` @@ -612,13 +612,13 @@ Listato 8.22 - Usare i metodi personalizzati è come usare i metodi generati echo $article; // Chiamerà il metodo magico __toString() } -### Sobrascrivere metodi esistenti +### Sovrascrivere i metodi esistenti -Se alcuni dei metodi generati nelle classi `Base` non soddisfano i tuoi requisiti, puoi comunque sovrascriverli nelle classi personalizzate. Sii sicuro che abbiano la stessa firma (ovvero lo stesso numero di parametri). +Se alcuni dei metodi generati nelle classi `Base` non soddisfano i requisiti, si può comunque sovrascriverli nelle classi personalizzate. Assicurarsi che abbiano la stessa firma (ovvero lo stesso numero di parametri). -Per esempio, il metodo `$article->getComments()` ritorna un array di oggetti `Comment`, senza alcun ordine particolare. Se vuoi avere i risultati ordinati per data di creazione, con gli ultimi commenti per primi, allora sovrascrivi il metodo `getComments()`, come mostrato nel Listato 8-23. Sii conscio che il metodo originale `getComments()` (collocato in `lib/model/om/BaseArticle.php`) si aspetta un oggetto Criteria ed una connessione come parametri, quindi la tua funzione deve fare lo stesso. +Per esempio, il metodo `$article->getComments()` restituisce un array di oggetti `Comment`, senza alcun ordine particolare. Se si vogliono i risultati ordinati per data di creazione, con gli ultimi commenti per primi, sovrascrivere il metodo `getComments()`, come mostrato nel Listato 8-23. Attenzione: il metodo originale `getComments()` (collocato in `lib/model/om/BaseArticle.php`) si aspetta un oggetto `Criteria` e una connessione come parametri, quindi la nuova funzione deve fare lo stesso. -Listato 8-23 - Sovrascivere metodi esistenti del modello, in `lib/model/Article.php` +Listato 8-23 - Sovrascrivere metodi esistenti del modello, in `lib/model/Article.php` [php] public function getComments($criteria = null, $con = null) @@ -629,7 +629,7 @@ Listato 8-23 - Sovrascivere metodi esistenti del modello, in `lib/model/Article. } else { - // Gli oggetti sono passati per riferimento in PHP5, quindi per evitare di modificare l'originale, devi clonarlo + // Gli oggetti sono passati per riferimento in PHP5, quindi per evitare di modificare l'originale, occorre clonarlo $criteria = clone $criteria; } $criteria->addDescendingOrderByColumn(CommentPeer::CREATED_AT); @@ -637,41 +637,41 @@ Listato 8-23 - Sovrascivere metodi esistenti del modello, in `lib/model/Article. return parent::getComments($criteria, $con); } -Il metodo personalizzato chiama infine quello della classe Base, ed è una buona pratica. Comunque, puoi completamente bypassarlo e ritornare il risultato che vuoi. +Il metodo personalizzato chiama infine quello della classe Base ed è una buona pratica. Comunque, lo si può aggirare completamente e restituire il risultato desiderato. ### Usare i comportamenti (behavior) del modello -Alcune modifiche al modello sono generiche e possono venire riutilizzate. Per esempio, i metodi per rendere un oggetto del modello ordinabile ed un blocco ottimistico per prevenire conflitti tra il salvataggio di oggetti concorrenti sono estensioni generiche che possono venir aggiunte a diverse classi. +Alcune modifiche al modello sono generiche e possono venire riutilizzate. Per esempio, i metodi per rendere un oggetto del modello ordinabile e un blocco ottimistico per prevenire conflitti tra il salvataggio di oggetti concorrenti sono estensioni generiche che possono venir aggiunte a diverse classi. -Symfony fornisce queste estensioni tramite i behavior. I behavior sono classi esterne che forniscono metodi aggiuntivi alle classi del modello. Le classi del modello contengono già degli "appigli" (hooks), e symfony sa come estenderle. +Symfony fornisce queste estensioni tramite i behavior. I behavior sono classi esterne che forniscono metodi aggiuntivi alle classi del modello. Le classi del modello contengono già degli "appigli" (hooks) e symfony sa come estenderle. -Per abilitare i behavior nelle tue classi del modello, devi modificare un'impostazione nel file `config/propel.ini`: +Per abilitare i behavior nelle classi del modello, occorre modificare un'impostazione nel file `config/propel.ini`: propel.builder.AddBehaviors = true // Il valore di default è false -Non c'è nessun behavior incluso in symfony di default, ma possono venir installati tramite plugins. Dopo che un behavior è installato, puoi assegnare il behavior ad una classe con una singola istruzione. Per esempio, se installi il plugin `sfPropelParanoidBehaviorPlugin` nella tua applicazione, puoi estendere una classe `Article` con questo behavior aggiungendo queste righe alla fine di `Article.class.php`: +Non c'è nessun behavior incluso in symfony di default, ma possono essere installati tramite plugin. Dopo che un behavior è installato, si può assegnare il behavior a una classe con una singola istruzione. Per esempio, se si installa il plugin `sfPropelParanoidBehaviorPlugin` nella propria applicazione, si può estendere una classe `Article` con questo behavior, aggiungendo queste righe alla fine di `Article.class.php`: [php] sfPropelBehavior::add('Article', array( 'paranoid' => array('column' => 'deleted_at') )); -Dopo aver ricostruito il modello, gli oggetti `Article` eliminati resteranno nel database, invisibile alle query creato usando l'ORM, a meno che non disabiliti temporaneamente il behavior con `sfPropelParanoidBehavior::disable()`. +Dopo aver ricostruito il modello, gli oggetti `Article` eliminati resteranno nel database, invisibile alle query create usando l'ORM, a meno che non si disabiliti temporaneamente il behavior con `sfPropelParanoidBehavior::disable()`. -In alternativa, puoi inoltre dichiarare behaviors direttamente dentro a `schema.yml`, aggiungendoli all'interno della chiave `_behaviors` (vedi il Listato 8-34 di seguito). +In alternativa, si possono dichiarare i behavior direttamente dentro allo `schema.yml`, aggiungendoli all'interno della chiave `_behaviors` (vedere il Listato 8-34 di seguito). -Controlla la lista dei plugin di symfony sul [repository](http://www.symfony-project.org/plugins/) ufficiale per trovare i behavior. Ognuno ha la sua documentazione e guida di installazione. +Controllare la lista dei plugin di symfony sul [repository](http://www.symfony-project.org/plugins/) ufficiale per trovare i behavior. Ognuno ha la sua documentazione e guida di installazione. -Extended Schema Syntax ----------------------- +Sintassi estesa dello schema +---------------------------- -A `schema.yml` file can be simple, as shown in Listing 8-3. But relational models are often complex. That's why the schema has an extensive syntax able to handle almost every case. +Un file `schema.yml` può essere semplice, come mostrato nel Listato 8-3. Ma i modelli relazionali sono spesso complessi. Per questo lo schema ha una sinstassi estesa, che consente di gestire quasi tutti i casi. -### Attributes +### Attributi -Connections and tables can have specific attributes, as shown in Listing 8-24. They are set under an `_attributes` key. +Le connessioni e le tabelle possono avere attributi specifici, come mostrato nel Listato 8-24. Questi sono sotto la chiave `_attributes`. -Listing 8-24 - Attributes for Connections and Tables +Listato 8-24 - Attributi per connessioni e tabelle [yml] propel: @@ -679,15 +679,15 @@ Listing 8-24 - Attributes for Connections and Tables blog_article: _attributes: { phpName: Article } -You may want your schema to be validated before code generation takes place. To do that, deactivate the `noXSD` attribute for the connection. The connection also supports the `defaultIdMethod` attribute. If none is provided, then the database's native method of generating IDs will be used--for example, `autoincrement` for MySQL, or `sequences` for PostgreSQL. The other possible value is `none`. +Si potrebbe voler validare lo schema prima di eseguire la generazione. Per farlo, disattivare l'attributo `noXSD` della connessione. La connessione supporta anche un attributo `defaultIdMethod`. Se non viene fornito, sarà usato il metodo nativo di generazione di ID, ad esempio `autoincrement` per MySQL o `sequences` per PostgreSQL. L'altro possibile valore è `none`. -The `package` attribute is like a namespace; it determines the path where the generated classes are stored. It defaults to `lib/model/`, but you can change it to organize your model in subpackages. For instance, if you don't want to mix the core business classes and the classes defining a database-stored statistics engine in the same directory, then define two schemas with `lib.model.business` and `lib.model.stats` packages. +L'attributo `package` è come un namespace: esso determina il percorso in cui mettere le classi generate. Il valore predefinito è `lib/model/`, ma lo si può cambiare per organizzare i modelli in pacchetti. Ad esempio, se non si vogliono mischiare le classi in una sola cartella, si possono definire due schemi: `lib.model.business` e `lib.model.stats`. -You already saw the `phpName` table attribute, used to set the name of the generated class mapping the table. +Abbiamo già visto l'attributo delle tabelle `phpName`, usato per impostare il nome della classe generata riferita a una tabella. -Tables that contain localized content (that is, several versions of the content, in a related table, for internationalization) also take two additional attributes (see Chapter 13 for details), as shown in Listing 8-25. +Le tabelle contenenti dati localizzati (cioè diverse versioni dello stesso contenuto, in una tabella correlata, per l'internazionalizzazione) posso accettare due ulteriori parametri (si veda il capitolo 13 per i dettagli), come mostrato nel Listato 8-25. -Listing 8-25 - Attributes for i18n Tables +Listato 8-25 - Attributi per le tabelle i18n [yml] propel: @@ -695,11 +695,11 @@ Listing 8-25 - Attributes for i18n Tables _attributes: { isI18N: true, i18nTable: db_group_i18n } >**SIDEBAR** ->Dealing with multiple Schemas +>Gestire schemi multipli > ->You can have more than one schema per application. Symfony will take into account every file ending with `schema.yml` or `schema.xml` in the `config/` folder. If your application has many tables, or if some tables don't share the same connection, you will find this approach very useful. +>Si può avere più di uno schema per applicazione. Symfony considererà ogni file il cui nome finisce per `schema.yml` o `schema.xml` nella cartella `config/`. Se l'applicazione ha molte tabelle o se alcune tabelle non condividono la stessa connessione, questo approccio può essere molto utile. > ->Consider these two schemas: +>Si considerino questi due schemi: > > [yml] > // In config/business-schema.yml @@ -718,10 +718,9 @@ Listing 8-25 - Attributes for i18n Tables > created_at: > > ->Both schemas share the same connection (`propel`), and the `Article` and `Hit` classes will be generated under the same `lib/model/` directory. Everything happens as if you had written only one schema. -> ->You can also have different schemas use different connections (for instance, `propel` and `propel_bis`, to be defined in `databases.yml`) and organize the generated classes in subdirectories: +>Entrambi gli schemi condividono la stessa connessione (`propel`) e le classi `Article` e `Hit` saranno generate sotto la stessa cartella `lib/model/`. È tutto come se avessimo un unico schema. > +>Si possono anche avere schemi diversi per connessioni diverse (per esempio, `propel` e `propel_bis`, da definire in `databases.yml`) e organizzare le classi generate in sotto-cartelle: > > [yml] > // In config/business-schema.yml @@ -740,23 +739,23 @@ Listing 8-25 - Attributes for i18n Tables > created_at: > > ->Many applications use more than one schema. In particular, some plug-ins have their own schema and package to avoid messing with your own classes (see Chapter 17 for details). +>Diverse applicazioni usano più di uno schema. In particolare, alcuni plugin hanno il loro schema e il loro `package`, per evitare di confondersi con le classi del progetto (si veda il capitolo 17 per i dettagli). -### Column Details +### Dettagli delle colonne -The basic syntax gives you two choices: let symfony deduce the column characteristics from its name (by giving an empty value) or define the type with one of the type keywords. Listing 8-26 demonstrates these choices. +La sintassi di base fornisce due scelte: lasciare che symfony deduca le caratteristiche delle colonne dal loro nome (dando un valore vuoto) o definire il tipo con una della chiavi. Il Listato 8-26 mostra queste scelte. -Listing 8-26 - Basic Column Attributes +Listato 8-26 - Attributi di base delle colonne [yml] propel: blog_article: - id: ~ # Let symfony do the work - title: varchar(50) # Specify the type yourself + id: ~ # symfony fa da solo + title: varchar(50) # specificato -But you can define much more for a column. If you do, you will need to define column settings as an associative array, as shown in Listing 8-27. +Ma si può definire di più per una colonna. Se si vuole, occorre definire le impostazioni della colonna come array associativo, come mostrato nel Listato 8-27. -Listing 8-27 - Complex Column Attributes +Listato 8-27 - Attributi complessi delle colonne [yml] propel: @@ -765,27 +764,27 @@ Listing 8-27 - Complex Column Attributes name: { type: varchar(50), default: foobar, index: true } group_id: { type: integer, foreignTable: db_group, foreignReference: id, onDelete: cascade } -The column parameters are as follows: +I parametri delle colonne sono i seguenti: - * `type`: Column type. The choices are `boolean`, `tinyint`, `smallint`, `integer`, `bigint`, `double`, `float`, `real`, `decimal`, `char`, `varchar(size)`, `longvarchar`, `date`, `time`, `timestamp`, `bu_date`, `bu_timestamp`, `blob`, and `clob`. - * `required`: Boolean. Set it to `true` if you want the column to be required. - * `size`: The size or length of the field for types that support it - * `scale`: Number of decimal places for use with decimal data type (size must also be specified) - * `default`: Default value. - * `primaryKey`: Boolean. Set it to `true` for primary keys. - * `autoIncrement`: Boolean. Set it to `true` for columns of type `integer` that need to take an auto-incremented value. - * `sequence`: Sequence name for databases using sequences for `autoIncrement` columns (for example, PostgreSQL and Oracle). - * `index`: Boolean. Set it to `true` if you want a simple index or to `unique` if you want a unique index to be created on the column. - * `foreignTable`: A table name, used to create a foreign key to another table. - * `foreignReference`: The name of the related column if a foreign key is defined via `foreignTable`. - * `onDelete`: Determines the action to trigger when a record in a related table is deleted. When set to `setnull`, the foreign key column is set to `null`. When set to `cascade`, the record is deleted. If the database engine doesn't support the set behavior, the ORM emulates it. This is relevant only for columns bearing a `foreignTable` and a `foreignReference`. - * `isCulture`: Boolean. Set it to `true` for culture columns in localized content tables (see Chapter 13). + * `type`: il tipo. Le scelte sono tra `boolean`, `tinyint`, `smallint`, `integer`, `bigint`, `double`, `float`, `real`, `decimal`, `char`, `varchar(size)`, `longvarchar`, `date`, `time`, `timestamp`, `bu_date`, `bu_timestamp`, `blob` e `clob`. + * `required`: Booleano. Impostare a `true` se si vuole che la colonna sia obbligatoria. + * `size`: La dimensione o la lunghezza del campo, per i tipi che la supportano. + * `scale`: Numero di cifre decimali, per il tipo `decimal` (occorre specificare anche `size`). + * `default`: Il valore predefinito. + * `primaryKey`: Booleano. Impostare a `true` per le chiavi primarie. + * `autoIncrement`: Booleano. Impostare a `true` per le colonne di tipo `integer` che devono avere un valore auto-incrementato. + * `sequence`: Nome della sequenza da usare per le colonne `autoIncrement` (per PostgreSQL e Oracle). + * `index`: Booleano. Impostare a `true` per un indice semplice o a `unique` per una chiave univoca sulla colonna. + * `foreignTable`: Un nome di tabella, usato per creare una chiave esterna. + * `foreignReference`: Il nome di una colonna correlata, se una chiave esterna è definita con `foreignTable`. + * `onDelete`: Determinea l'azione da eseguire quando un record viene cancellato. Se impostato a `setnull`, la colonna della chiave esterna viene posta a `null`. Se impostato a `cascade`, il record viene cancellato. Se il database non supporta questi comportamenti, l'ORM li emula. Questo è rilevante solo per colonne con `foreignTable` e `foreignReference`. + * `isCulture`: Booleano. Impostare a `true` per colonne che riportano la cultura nelle tabelle localizzate (vedere capitolo 13). -### Foreign Keys +### Chiavi esterne -As an alternative to the `foreignTable` and `foreignReference` column attributes, you can add foreign keys under the `_foreignKeys:` key in a table. The schema in Listing 8-28 will create a foreign key on the `user_id` column, matching the `id` column in the `blog_user` table. +Come alternativa agli attributi `foreignTable` e `foreignReference` delle colonne, si può usare la chiave `_foreignKeys:` in una tabella. Lo schema nel Listato 8-28 crea una chiave esterna per la colonna `user_id` verso la colonna `id` della tabella `blog_user`. -Listing 8-28 - Foreign Key Alternative Syntax +Listato 8-28 - Sintassi alternativa per le chiavi esterne [yml] propel: @@ -800,23 +799,23 @@ Listing 8-28 - Foreign Key Alternative Syntax references: - { local: user_id, foreign: id } -The alternative syntax is useful for multiple-reference foreign keys and to give foreign keys a name, as shown in Listing 8-29. +La sintassi alternativa è utile per chiavi esterne multiple e per dare un nome alle chiavi esterne, come mostrato nel Listato 8-29. -Listing 8-29 - Foreign Key Alternative Syntax Applied to Multiple Reference Foreign Key +Listato 8-29 - Sintassi alternativa per le chiavi esterne applicata a chiavi esterne multiple _foreignKeys: - my_foreign_key: + nome_chiave: foreignTable: db_user onDelete: cascade references: - { local: user_id, foreign: id } - { local: post_id, foreign: id } -### Indexes +### Indici -As an alternative to the `index` column attribute, you can add indexes under the `_indexes:` key in a table. If you want to define unique indexes, you must use the `_uniques:` header instead. For columns that require a size, because they are text columns, the size of the index is specified the same way as the length of the column using parentheses. Listing 8-30 shows the alternative syntax for indexes. +Come alternativa all'attributo `index` di una colonna, si possono aggiungere indici sotto la chiave `_indexes:` in una tabella. Se si vogliono definire chiavi univoche, occorre invece usare `_uniques:`. Per colonne che richiedono una dimensione, perché sono colonne testuali, la dimensione dell'indice è specificata nello stesso modo della lunghezza delle colonne, usando le parentesi. Il Listato 8-30 mostra la sintassi alternativa per gli indici. -Listing 8-30 - Indexes and Unique Indexes Alternative Syntax +Listato 8-30 - Sintassi alternativa per indici e chiavi univoche [yml] propel: @@ -825,38 +824,38 @@ Listing 8-30 - Indexes and Unique Indexes Alternative Syntax title: varchar(50) created_at: _indexes: - my_index: [title(10), user_id] + mio_indice: [title(10), user_id] _uniques: - my_other_index: [created_at] + mio_indice_2: [created_at] -The alternative syntax is useful only for indexes built on more than one column. +La sintassi alternativa è utile solo per indici su più colonne. -### Empty Columns +### Colonne vuote -When meeting a column with no value, symfony will do some magic and add a value of its own. See Listing 8-31 for the details added to empty columns. +Quando incontra una colonna senza valori, symfony fa alcune magie per aggiungere i suoi valori. Si veda il Listato 8-31 per i dettagli aggiunti alle colonne vuote. -Listing 8-31 - Column Details Deduced from the Column Name +Listato 8-31 - Dettagli delle colonne dedotti dal nome della colonna - // Empty columns named id are considered primary keys + // Colonne vuote chiamate "id" sono considerate chiavi primarie id: { type: integer, required: true, primaryKey: true, autoIncrement: true } - // Empty columns named XXX_id are considered foreign keys + // Colonne vuote chiamate "XXX_id" sono considerate chiavi esterne foobar_id: { type: integer, foreignTable: db_foobar, foreignReference: id } - // Empty columns named created_at, updated at, created_on and updated_on - // are considered dates and automatically take the timestamp type + // Colonne vuote chiamate "created_at", "updated at", "created_on" e "updated_on" + // sono considerate date e diventano di tipo timestamp created_at: { type: timestamp } updated_at: { type: timestamp } -For foreign keys, symfony will look for a table having the same `phpName` as the beginning of the column name, and if one is found, it will take this table name as the `foreignTable`. +Per le chiavi esterne, symfony cercherà una tabella con lo stesso `phpName` dell'inizio del nome della colonna e, se ne troverà uno, userà il suo nome come `foreignTable`. -### I18n Tables +### Tabelle I18n -Symfony supports content internationalization in related tables. This means that when you have content subject to internationalization, it is stored in two separate tables: one with the invariable columns and another with the internationalized columns. +Symfony supporta l'internazionalizzazione dei contenuti tramite tabelle dedicate. Questo significa che quando si ha un contenuto da internazionalizzare, viene memorizzato in due tabelle separate: una per le colonne che non cambiano e una per le colonne da internazionalizzare. -In a `schema.yml` file, all that is implied when you name a table `foobar_i18n`. For instance, the schema shown in Listing 8-32 will be automatically completed with columns and table attributes to make the internationalized content mechanism work. Internally, symfony will understand it as if it were written like Listing 8-33. Chapter 13 will tell you more about i18n. +In un file `schema.yml`, tutto è implicito quando si dà il nome `pippo_i18n` a una tabella. Per esempio, lo schema mostrato nel Listato 8-32 verrà automaticamente completato con colonne e attributi per far funzionare il meccanismo di internazionalizzazione. Internamente, symfony lo interpreterà come se fosse scritto come nel Listato 8-33. Il capitolo 13 contiene maggiori informazioni su i18n. -Listing 8-32 - Implied i18n Mechanism +Listato 8-32 - Meccanismo i18n implicito [yml] propel: @@ -867,7 +866,7 @@ Listing 8-32 - Implied i18n Mechanism db_group_i18n: name: varchar(50) -Listing 8-33 - Explicit i18n Mechanism +Listato 8-33 - Meccanismo i18n esplicito [yml] propel: @@ -881,11 +880,11 @@ Listing 8-33 - Explicit i18n Mechanism culture: { isCulture: true, type: varchar(7), required: true,primaryKey: true } name: varchar(50) -### Behaviors +### Comportamenti -Behaviors are model modifiers provided by plug-ins that add new capabilities to your Propel classes. Chapter 17 explains more about behaviors. You can define behaviors right in the schema, by listing them for each table, together with their parameters, under the `_behaviors` key. Listing 8-34 gives an example by extending the `BlogArticle` class with the `paranoid` behavior. +I comportamenti sono modificatori dei modelli forniti da plugin, che aggiungono nuove capacità alle classi di Propel. Il capitolo 17 parla più approfonditamente dei comportamenti. I comportamenti si possono definire nello schema, elencandoli per ciascuna tabella, insieme con i loro parametri, sotto la chiave `_behaviors`. Il Listato 8-34 fornisce un esempio estendendo la classe `BlogArticle` con il comportamento `paranoid`. -Listing 8-34 - Behaviors Declaration +Listato 8-34 - Dichiarazione dei comportamenti [yml] propel: @@ -894,13 +893,13 @@ Listing 8-34 - Behaviors Declaration _behaviors: paranoid: { column: deleted_at } -### Beyond the schema.yml: The schema.xml +### Oltre lo schema.yml: lo schema.xml -As a matter of fact, the `schema.yml` format is internal to symfony. When you call a propel- command, symfony actually translates this file into a `generated-schema.xml` file, which is the type of file expected by Propel to actually perform tasks on the model. +Di fatto, il formato `schema.yml` è interno a symfony. Quando si richiama un comando di Propel, symfony traduce tale file in un file `generated-schema.xml`, che è il tipo di file che Propel si aspetta per eseguire effettivamente ciò che deve fare sul modello. -The `schema.xml` file contains the same information as its YAML equivalent. For example, Listing 8-3 is converted to the XML file shown in Listing 8-35. +Il file `schema.xml` contiene le stesse informazioni del suo equivalente YAML. Per esempio, il Listato 8-3 viene convertito nel file XML mostrato nel Listato 8-35. -Listing 8-35 - Sample `schema.xml`, Corresponding to Listing 8-3 +Listato 8-35 - Esempio di `schema.xml`, corrispondente al Listato 8-3 [xml] @@ -923,87 +922,87 @@ Listing 8-35 - Sample `schema.xml`, Corresponding to Listing 8-3 -The description of the `schema.xml` format can be found in the documentation and the "Getting Started" sections of the Propel project [website](http://propel.phpdb.org/docs/user_guide/chapters/appendices/AppendixB-SchemaReference.html). +La descrizione del formato `schema.xml` si trova nella sezione "Getting Started" del [sito di Propel](http://www.propelorm.org/wiki/Documentation/1.4/Schema-Reference). -The YAML format was designed to keep the schemas simple to read and write, but the trade-off is that the most complex schemas can't be described with a `schema.yml` file. On the other hand, the XML format allows for full schema description, whatever its complexity, and includes database vendor-specific settings, table inheritance, and so on. +Il formato YAML è stato disegnato per mantenere gli schemi semplici da leggere e da scrivere, ma il prezzo da pagare è la difficoltà di descrivere schemi più complessi con un file `schema.yml`. D'altro canto, il formato XML consente una descrizione completa dello schema, qualunque complessità esso abbia, e include impostazioni specifiche per i database, ereditarietà delle tabelle e così via. -Symfony actually understands schemas written in XML format. So if your schema is too complex for the YAML syntax, if you have an existing XML schema, or if you are already familiar with the Propel XML syntax, you don't have to switch to the symfony YAML syntax. Place your `schema.xml` in the project `config/` directory, build the model, and there you go. +Symfony comprende anche gli schemi scritti in formato XML. Quindi, se si ha uno schema troppo complesso per la sintassi YAML o se si ha uno schema XML già esistente, non è necessario passare alla sintassi YAML. Basta mettere il proprio `schema.xml` nella cartella `config/` del progetto directory e costruire il modello. >**SIDEBAR** >Propel in symfony > ->All the details given in this chapter are not specific to symfony, but rather to Propel. Propel is the preferred object/relational abstraction layer for symfony, but you can choose an alternative one. However, symfony works more seamlessly with Propel, for the following reasons: +>Tutti i dettagli dati in questo capitolo non sono specifici di symfony, ma piuttosto di Propel. Si può scegliere un livello di astrazione di ogetti/relazioni, ma symfony funziona molto bene con Propel, per le seguenti ragioni: > ->All the object data model classes and the `Criteria` class are autoloading classes. As soon as you use them, symfony will include the right files, and you don't need to manually add the file inclusion statements. In symfony, Propel doesn't need to be launched nor initialized. When an object uses Propel, the library initiates by itself. Some symfony helpers use Propel objects as parameters to achieve high-level tasks (such as pagination or filtering). Propel objects allow rapid prototyping and generation of a backend for your application (Chapter 14 provides more details). The schema is faster to write through the `schema.yml` file. +>Tutti gli oggetti delle classi del modello e le classi `Criteria` si caricano automaticamente. Non appena le si usa, symfony includerà i file giusti e non si avrà bisogno di istruzioni di inclusione. In symfony, Propel non ha bisogno di essere lanciato né inizializzato. Quando un oggetto usa Propel, la libreria si inizializza da sé. Alcuni helper di symfony usano gli oggetti di Propel per compiti ad alto livello (come paginazione o filtri). Gli oggetti di Propel consentono una prototipazione rapida e la generazione di un backend per la propria applicazione (il capitolo 14 fornisce maggiori dettagli in merito). Lo schema è più veloce da scrivere con il file `schema.yml`. > ->And, as Propel is independent of the database used, so is symfony. +>Infine, Propel è indipendente dal database usato, così come lo è symfony. -Don't Create the Model Twice ----------------------------- +Non creare il modello due volte +------------------------------- -The trade-off of using an ORM is that you must define the data structure twice: once for the database, and once for the object model. Fortunately, symfony offers command-line tools to generate one based on the other, so you can avoid duplicate work. +Lo svantaggio nell'utilizzo di un ORM è che bisogna definire la struttura dati due volte: una per il database e una per il modello a oggetti. Per fortuna, symfony fornisce degli strumenti a riga di comando per generare l'uno basato sull'altro, in modo da evitare la duplicazione del lavoro. -### Building a SQL Database Structure Based on an Existing Schema +### Creare l'SQL della struttura di un database basandosi su uno schema esistente -If you start your application by writing the `schema.yml` file, symfony can generate a SQL query that creates the tables directly from the YAML data model. To use the query, go to your root project directory and type this: +Se si inizia l'applicazione scrivendo il file `schema.yml`, symfony può generare una query SQL che crea le tabelle direttamente dal modello YAML dei dati. Per generare la query, andare nella cartella radice del progetto e digitare: $ php symfony propel:build-sql -A `lib.model.schema.sql` file will be created in `myproject/data/sql/`. Note that the generated SQL code will be optimized for the database system defined in the `phptype` parameter of the `propel.ini` file. +Verrà creato un file `lib.model.schema.sql` in `mioprogetto/data/sql/`. Notare che il codice SQL generato sarà ottimizzato per il sistema di database definito nel parametro `phptype` o nel file `propel.ini`. -You can use the `schema.sql` file directly to build the tables. For instance, in MySQL, type this: +Si può usare il file `lib.model.schema.sql` direttamente per costruire le tabelle. Ad esempio, in MySQL, digitare: $ mysqladmin -u root -p create blog $ mysql -u root -p blog < data/sql/lib.model.schema.sql -The generated SQL is also helpful to rebuild the database in another environment, or to change to another DBMS. If the connection settings are properly defined in your `propel.ini`, you can even use the `php symfony propel:insert-sql` command to do this automatically. +Il codice SQL generato è utile anche per ricostruire il database in un altro ambiente o per passare a un altro database. Se le impostazioni di connessioni sono definite correttamente in `propel.ini`, si può anche usare il comando `php symfony propel:insert-sql` per farlo automaticamente. >**TIP** ->The command line also offers a task to populate your database with data based on a text file. See Chapter 16 for more information about the `propel:data-load` task and the YAML fixture files. +>La riga di comando offre anche un task per popolare il database con i dati caricati da un file di testo. Vedere il capitolo 16 per maggiori informazioni sul task `propel:data-load` e i file delle fixture in YAML. -### Generating a YAML Data Model from an Existing Database +### Generare un modello dei dati YAML da un database esistente -Symfony can use Propel to generate a `schema.yml` file from an existing database, thanks to introspection (the capability of databases to determine the structure of the tables on which they are operating). This can be particularly useful when you do reverse-engineering, or if you prefer working on the database before working on the object model. +Symfony può usare Propel per generare un file `schema.yml` da un database esistente, grazie alla introspezione (la capacità dei database di determinare la struttura delle tabelle sulle quali stanno operando). Questo può essere particolarmente utile quando si fa reverse-engineering, oppure quando si preferisce lavorare sul database prima di lavorare sul modello a oggetti. -In order to do this, you need to make sure that the project `databases.yml` file points to the correct database and contains all connection settings, and then call the `propel:build-schema` command: +Per fare ciò, è necessario assicurarsi che il file `databases.yml` del progetto punti al database corretto e contenga tutte le informazioni per la connessione. Quindi lanciare il comando `propel:build-schema`: $ php symfony propel:build-schema -A brand-new `schema.yml` file built from your database structure is generated in the `config/` directory. You can build your model based on this schema. +Dalla struttura del database viene generato un nuovo file `schema.yml` nella cartella `config/`. Si può costruire il modello basato su questo schema. -The schema-generation command is quite powerful and can add a lot of database-dependent information to your schema. As the YAML format doesn't handle this kind of vendor information, you need to generate an XML schema to take advantage of it. You can do this simply by adding an `xml` argument to the `build-schema` task: +Il comando di generazione dello schema è potente e può aggiungere allo schema molte informazioni dipendenti dal database. Poiché il formato YAML non gestisce questo tipo di informazioni, occorre generare uno schema XML per poterle sfruttare. Lo si può fare semplicemente aggiungendo un parametro `xml` al task `build-schema`: $ php symfony propel:build-schema --xml -Instead of generating a `schema.yml` file, this will create a `schema.xml` file fully compatible with Propel, containing all the vendor information. But be aware that generated XML schemas tend to be quite verbose and difficult to read. +Invece di generare un file `schema.yml`, verrà creato un file `schema.xml` pienamente compatibile con Propel, contenente tutte le informazioni specifiche del database. Si faccia però attenzione, perché gli schemi XML tendono a essere molto prolissi e difficili da leggere. >**SIDEBAR** ->The `propel.ini` Configuration +>La configurazione `propel.ini` > ->This file contains other settings used to configure the Propel generator to make generated model classes compatible with symfony. Most settings are internal and of no interest to the user, apart from a few: +>Questo file contiene altre impostazioni usate per configurare il generatore di Propel per rendere le classi del modello generate maggiormente compatibili con symfony. La maggior parte delle impostazioni sono di uso interno e senza interesse per l'utente, tranne alcune: > -> // Base classes are autoloaded in symfony -> // Set this to true to use include_once statements instead -> // (Small negative impact on performance) +> // Le classi Base sono autocaricate in symfony +> // Impostare a true per usare invece include_once +> // (Piccolo impatto negativo sulle prestazioni) > propel.builder.addIncludes = false > -> // Generated classes are not commented by default -> // Set this to true to add comments to Base classes -> // (Small negative impact on performance) +> // Le classi generate non sono commentate +> // Impostare a true per aggiungere i commenti alle classi Base +> // (Piccolo impatto negativo sulle prestazioni) > propel.builder.addComments = false > -> // Behaviors are not handled by default -> // Set this to true to be able to handle them +> // I comportamenti non sono gestiti +> // Impostare a true per poterli gestire > propel.builder.AddBehaviors = false > > ->After you make a modification to the `propel.ini` settings, don't forget to rebuild the model so the changes will take effect. +>Dopo una modifica al file `propel.ini`, non dimenticare di ricostruire il modello, in modo che i cambiamenti abbiano effetto. -Summary -------- +Riepilogo +--------- -Symfony uses Propel as the ORM and PHP Data Objects as the database abstraction layer. It means that you must first describe the relational schema of your database in YAML before generating the object model classes. Then, at runtime, use the methods of the object and peer classes to retrieve information about a record or a set of records. You can override them and extend the model easily by adding methods to the custom classes. The connection settings are defined in a `databases.yml` file, which can support more than one connection. And the command line contains special tasks to avoid duplicate structure definition. +Symfony usa Propel come ORM e gli oggetti dei dati di PHP per il livello di astrazione del database. Ciò significa che è necessario prima descrivere lo schema relazionale del database in YAML prima di generare le classi del modello a oggetti. Poi, in fase di runtime, utilizzare i metodi dell'oggetto e le classi peer per recuperare informazioni su un record o un insieme di record. È possibile sovrascrivere ed estendere facilmente il modello aggiungendo metodi alle classi personalizzate. Le impostazioni di connessione sono definite in un file `databases.yml`, che può supportare più di una connessione. E la linea di comando contiene dei task speciali per evitare di duplicare la definizione della struttura. -The model layer is the most complex of the symfony framework. One reason for this complexity is that data manipulation is an intricate matter. The related security issues are crucial for a website and should not be ignored. Another reason is that symfony is more suited for middle- to large-scale applications in an enterprise context. In such applications, the automations provided by the symfony model really represent a gain of time, worth the investment in learning its internals. +Il livello del modello è il più complesso del framework symfony. Una delle ragioni di questa complessità è che la manipolazione dei dati è una questione intricata. I problemi di sicurezza correlati sono fondamentali per un sito web e non devono essere ignorati. Un'altra ragione è che symfony è più adatto ad applicazioni di medio-grandi dimensioni in contesto enterprise. In tali applicazioni, le automazioni fornite dal modello di symfony possono davvero rappresentare un guadagno di tempo che vale l'investimento per apprendere il suo funzionamento. -So don't hesitate to spend some time testing the model objects and methods to fully understand them. The solidity and scalability of your applications will be a great reward. +Quindi non esitate nel dedicare un periodo di prova al modello a oggetti e ai metodi, per comprenderli pienamente. La solidità e la scalabilità delle applicazioni saranno la ricompensa. diff --git a/reference/it/10-Routing.markdown b/reference/it/10-Routing.markdown index af4ad4f..a8c7551 100644 --- a/reference/it/10-Routing.markdown +++ b/reference/it/10-Routing.markdown @@ -248,7 +248,7 @@ metodo è chiamato con i parametri della rotta scansionata come parametro. *Predefinito*: none L'opzione `method_for_query` definisce il metodo da chiamare sul modello per -recuperare l'oggetto (o gli oggetti) associati con la richiesta corrente. L'ggetto della richiesta +recuperare l'oggetto (o gli oggetti) associati con la richiesta corrente. L'oggetto della richiesta corrente è passato come parametro. Se l'opzione non è assegnata, la richiesta è solo "eseguita" con il metodo diff --git a/tutorial/it/upgrade.markdown b/tutorial/it/upgrade.markdown index 220de6c..e926dd1 100644 --- a/tutorial/it/upgrade.markdown +++ b/tutorial/it/upgrade.markdown @@ -229,13 +229,13 @@ escape solamente i caratteri di barra `\`, le virgolette `'` e `"` e gli "a capo Integrazione con Doctrine ------------------------- -### Versione Richiesta di Doctrine +### Versione richiesta di Doctrine Gli external verso Doctrine sono stati aggiornati all'ultima versione di Doctrine 1.2. Si possono avere informazioni sulle novità di Doctrine 1.2 [qui](http://www.doctrine-project.org/upgrade/1_2). -### Cancellazione nell'Admin Generator +### Cancellazione nell'admin generator La cancellazione multipla nell'admin generator è stata modificata per scorrere le righe ed eseguire il metodo `delete()` su ciascuna di esse @@ -243,7 +243,7 @@ singolarmente, piuttosto che eseguire una singola query DQL per cancellarle tutte. Questo per fare in modo che siano invocati gli eventi per la cancellazione di ogni singola riga. -### Sovrascrittura dello Schema Doctrine dei Plugin +### Sovrascrittura dello schema doctrine dei plugin Si può sovrascrivere il modello incluso in uno schema YAML di un plugin, semplicemente definendo lo stesso modello nel proprio schema locale. diff --git a/tutorial/it/whats-new.markdown b/tutorial/it/whats-new.markdown index d216ffd..901aaf5 100644 --- a/tutorial/it/whats-new.markdown +++ b/tutorial/it/whats-new.markdown @@ -84,7 +84,7 @@ I primi tre sostituiscono i widget `sfWidgetFormI18nSelectLanguage`, `sfWidgetFormI18nSelectCurrency` e `sfWidgetFormI18nSelectCountry`, che ora sono deprecati. -### Interfaccia Fluida +### Interfaccia fluida I widget ora implementano un'interfaccia fluida per i seguenti metodi: @@ -151,7 +151,7 @@ Sono stati aggiunti i seguenti validatori: * `sfValidatorI18nChoiceTimezone` -### Messaggi di Errore Predefiniti +### Messaggi di errore predefiniti Si possono ora definire dei messaggi di errore predefiniti in modo globale, usando il metodo `sfForm::setDefaultMessage()`: @@ -180,7 +180,7 @@ determinato nel modo seguente: * Se non definito, usa il messaggio predefinito dal validatore stesso (quando il messaggio è stato aggiunto col metodo `addMessage()`). -### Interfaccia Fluida +### Interfaccia fluida I validatori ora implementano un'interfaccia fluida per i seguenti metodi: @@ -292,7 +292,7 @@ nel suo metodo `configure()`: Richiamando `disableLocalCSRFProtection()`, la protezione CSRF sarà disabilitata, anche se si passa una stringa segreta CSRF all'istanza del form. -### Interfaccia Fluida +### Interfaccia fluida Alcuni metodi di `sfForm` ora implementano un'interfaccia fluida: `addCSRFProtection()`, `setValidators()`, `setValidator()`, `setValidatorSchema()`, @@ -315,7 +315,7 @@ eseguire `symfony cc` dopo l'aggiunta di una nuova classe al progetto. Test ---- -### Accelerazione dei Test +### Accelerazione dei test Quando si hanno molti test, lanciarli tutti dopo ogni modifica può portar via molto tempo, specialmente quando alcuni test falliscono. Questo perché @@ -335,7 +335,7 @@ passeranno e saranno quindi rimossi dalle esecuzioni successive. Quando tutti i test passano di nuovo, tutti i test vengono eseguiti... si può quindi ripetere a piacere. -### Test Funzionali +### Test funzionali Quando una richiesta genera un'eccezione, il metodo `debug()` del tester della risposta ora manda in output una rappresentazione testuale leggibile @@ -354,7 +354,7 @@ Inoltre sostitusce il metodo `contains()`, meno potente: matches('!/Ho \d+ mele/i')-> // si possono usare anche i modificatori end(); -### Output XML Compatibile con JUnit +### Output XML compatibile con JUnit I task dei test ora possono inviare in output un file XML compatibile con JUnit, usando l'opzione `--xml`: @@ -369,7 +369,7 @@ dei fallimenti: $ php symfony test:all -t -### Colorazione dell'Output di Lime +### Colorazione dell'output di Lime Da symfony 1.3/1.4, lime si comporta bene riguardo alla colorazione. Questo vuol dire che si può omettere quasi sempre il secondo parametro del costruttore @@ -623,12 +623,12 @@ Il task `generate:app` ora cerca uno scheletro di cartelle nella cartella `data/skeleton/app` del progetto, prima di usare lo scheletro predefinito distribuito con symfony. -### Invio di Email da un Task +### Invio di email da un task Si può ora inviare facilmente una email da un task, usando il metodo `getMailer()`. -### Usare il Routing in un Task +### Usare il routing in un task Si può ora recuperare facilmente l'oggetto routing da un task, usando il metodo `getRouting()`. @@ -642,7 +642,7 @@ Quando viene lanciata un'eccezione durante un autoload, symfony ora la cattura e mostra l'errore all'utente. Questo dovrebbe risolvere il problema delle pagine bianche. -### Web Debug Toolbar +### Web debug toolbar Se possibile, la web debug toolbar ora viene mostrata anche sulle pagine delle eccezioni, nell'ambiente di sviluppo. @@ -730,7 +730,7 @@ in `ProjectConfiguration`: Routing ------- -### Richieste Predefinite +### Richieste predefinite La richiesta predefinita `\d+` è ora applicata a `sfObjectRouteCollection` solo quando l'opzione `column` è il predefinito `id`. Questo vuol dire @@ -752,7 +752,7 @@ Consente di registrare dei parametri predefiniti per ogni rotta generata: CLI --- -### Colorazione dell'Otput +### Colorazione dell'output Symfony prova a indovinare se la console supporta i colori, quando si usano gli strumenti della CLI. Ma a volte symfony si sbaglia; ad esempio quando si @@ -864,7 +864,7 @@ Doctrine è stato aggiornato alla versione 1.2. Si visiti il sito di Doctrine per ulteriori informazioni sul suo aggiornamento (http://www.doctrine-project.org/documentation/1_2/en). -### Generazione delle Classi dei Form +### Generazione delle classi dei form È ora possibile specificare delle opzioni aggiuntive per symfony nei file YAML degli schema di Doctrine. Abbiamo aggiunto alcune opzioni per disabilitare la @@ -888,13 +888,13 @@ nel modo seguente: type: integer primary: true -### Ereditarietà delle Classi dei Form +### Ereditarietà delle classi dei form Quando si generano form dai modelli, i modelli contengono ereditarietà. Le classi figlie generate rispetteranno l'ereditarietà e genereranno form che seguono la stessa struttura di ereditarietà. -### Nuovi Task +### Nuovi task Abbiamo introdotto alcuni nuovi task che aiutano nello sviluppo con Doctrine. @@ -952,7 +952,7 @@ equivale a eseguire questi comandi: $ php symfony doctrine:insert-sql $ php symfony doctrine:data-load -#### Altri Build +#### Altri build Il nuovo task `doctrine:build` consente di specificare esattamente cosa si vuole che symfony e Doctrine costruiscano. Questo task replica la @@ -1009,7 +1009,7 @@ file in TextMate. Questo nuovo task genererà automaticamente delle classi per una completa migrazione, in base agli schemi vecchi e a quelli nuovi. -### Setter e Getter di Date +### Setter e getter di date Abbiamo aggiunto nuovi metodi per recuperare i valori di date o timestamp di Doctrine come istanze di oggetti DateTime di PHP. @@ -1038,7 +1038,7 @@ si può trarre vantaggio dalla nuova opzione `dry-run`. $ php symfony doctrine:migrate --dry-run -### Output dei Task DQL come Tabelle di Dati +### Output dei task DQL come tabelle di dati Quando si eseguiva il comando `doctrine:dql`, questo mostrava i dati solo come YAML. Abbiamo aggiunto una nuova opzione `--table`. Tale opzione consente @@ -1181,7 +1181,7 @@ L'uso di una diversa versione di Doctrine è facile, basta impostare sfConfig::set('sf_doctrine_dir', '/path/to/doctrine/lib'); } -Web Debug Toolbar +Web debug toolbar ----------------- ### `sfWebDebugPanel::setStatus()` @@ -1207,7 +1207,7 @@ all'opzione `request_parameters`: Partial ------- -### Miglioramenti agli Slot +### Miglioramenti agli slot Gli helper `get_slot()` e `include_slot()` ora accettano un secondo parametro per specificare il contenuto predefinito dello slot, da @@ -1254,7 +1254,7 @@ Due parametri sono disponibili in `factories.yml`: In pratica, dice se la cache della pagina debba essere dipendente dal nome dell'host. -### Più Cache +### Più cache Il gestore della cache delle viste non rifiuta più di mettere in cache in presenza di valori in `$_GET` o `$_POST`.La logica ora conferma solo