Development

Documentation/it_IT/book/1.1/14-Generators (diff)

You must first sign up to be able to contribute.

Changes from Version 1 of Documentation/it_IT/book/1.1/14-Generators

Show
Ignore:
Author:
garak (IP: 85.18.214.242)
Timestamp:
10/31/08 14:59:23 (9 years ago)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/it_IT/book/1.1/14-Generators

    v0 v1  
     1{{{ 
     2#!WikiMarkdown 
     3 
     4Capitolo 14 - Generatori 
     5======================== 
     6 
     7>**CAUTION** 
     8>Questo capitolo descrive il sistema di generazione dell'amministrazione, che utilizza ancora il sistema delle form della versione 1.0. Le informazioni sul generatore CRUD sono state spostate nel libro "Guida alle form di symfony", poiché esso usa il nuovo framework delle form. 
     9 
     10Molte applicazioni sono basate su dati memorizzati in un database, ed offrono interfacce per la loro gestione. Il noioso e ripetitivo lavoro di creazione di tali moduli fornendo alcune funzionalità basate su Propel. Se il tuo modello è definito correttamente, symfony potrebbe anche generare un intero sito di amministrazione. Questo capitolo descrive l'uso dell'administration generator, distribuito col plugin Propel. È basato su di un file di configurazione con una sintassi completa, per cui la maggior parte del presente capitolo descriverà le varie possibilità dell'administration generator. 
     11 
     12 
     13Generazione di codice basata sul modello 
     14---------------------------------------- 
     15 
     16In un'applicazione web le operazioni di accesso ai dati possono venire catalogate come segue: 
     17  * Creazione di record 
     18  * Selezione di record 
     19  * Modifica di record 
     20  * Eliminazione di record 
     21 
     22Tali operazioni sono talmente comuni da avere un acronimo dedicato: CRUD. Ad esempio, in forum la lista degli ultimi post è una selezione di record, mentre l'inserimento di una risposta corrisponde ad un'operazione di creazione. 
     23 
     24Le azioni di base ed i template che implementano le operazioni CRUD per una data tabella vengono ripetute continuamente nelle applicazioni web. In symfony, il layer del modello contiene abbastanza informazioni da consentire la generazione del codice per le operazioni CRUD, così da velocizzare la parte iniziale delle interfacce di backend. 
     25 
     26### Esempio di modello dei dati 
     27 
     28Durante questo capitolo i listati mostreranno le funzionalità dei generatori basandosi su un semplice esempio, che ti ricorderà il Capitolo 8. Si tratta del noto esempio di applicazione weblog, contenente le due classi `Article` e `Comment`. Il Listato 14-1 ne mostra lo schema, illustrato in Figura 14-1. 
     29 
     30Listato 14-1 - `schema.yml` di un esempio di weblog 
     31 
     32    [php] 
     33    propel: 
     34      blog_article: 
     35        _attributes: { phpName: Article } 
     36        id: 
     37        title:       varchar(255) 
     38        content:     longvarchar 
     39        created_at: 
     40      blog_comment: 
     41        _attributes: { phpName: Comment } 
     42        id: 
     43        article_id: 
     44        author:      varchar(255) 
     45        content:     longvarchar 
     46        created_at: 
     47 
     48Figura 14-1 - Esempio di modello dei dati 
     49 
     50![Esempio di modello dei dati](http://www.symfony-project.org/images/book/1_1/F1401.png "Esempio di modello dei dati") 
     51 
     52Non c'è una regola particolare da seguire durante la creazione dello schema per permettere la generazione del codice. Symfony utilizzerà lo schema così com'è ed interpreterà i suoi attributi per generare una administration. 
     53 
     54>**TIP** 
     55>Per recepire il meglio di questo capitolo sarebbe meglio che tu mettessi in pratica gli esempi. Avrai una panoramica migliore del codice generato da symfony e cosa puo' essere fatto con esso se segui passo passo gli esempi dei listati. Per cui sei invitato a creare una struttura dati come quella descritta precedentemente per creare un database con le tabelle `blog_article` e `blog_comment`, ed a popolarlo con dati di esempio. 
     56 
     57Amministrazione 
     58--------------- 
     59 
     60Per il backend della tua applicazione symfony può generare anche moduli più avanzati, ma sempre basandosi sul file `schema.yml`. Puoi creare un intero sito di amministrazione tramite i moduli generati. Gli esempi di questa sezione descriveranno i moduli di amministrazione di un'applicazione di backend. Se il tuo progetto non ha un'applicazione di backend, creane lo scheletro adesso tramite il task `init-app`: 
     61 
     62    symfony generate:app backend 
     63 
     64I moduli di amministrazione interpretano il modello tramite un file di configurazione particolare chiamato `generator.yml`, che può essere modificato per estendere i componenti generati ed il look and feel del modulo. Tali moduli beneficiano dei meccanismi descritti nei capitoli precedenti (layout, validation, routing, configurazioni personalizzate, autoloading, e così via). Puoi inoltre  sovrascrivere le azioni o i template generati, per poter integrare nell'amministrazione generate le tue proprie funzionalità, ma `generator.yml` si dovrebbe occupare dei requisiti più comuni e restringere il codice PHP solo a necessità specifiche. 
     65 
     66>**NOTE** 
     67>Poiché l'admin generator usa il sistema di validazione di symfony 1.0, il plugin `sfCompat10` viene abilitato automaticamente. 
     68 
     69### Inizializzazione di un modulo di amministrazione 
     70 
     71In symfony costruisci un'amministrazione per modulo. Esso viene generato tramite un'oggetto Propel utilizzando il task `propel:init-admin`: 
     72 
     73    symfony propel:init-admin backend article Article 
     74 
     75Questa chiamata è sufficiente a creare il modulo `article` nell'applicazione di backend basato sulla definizione della classe `Article`, accessibile tramite: 
     76 
     77    http://localhost/backend.php/article 
     78 
     79Il look and feel del modulo generato, illustrato nelle Figure 14-5 e 14-6, è abbastanza sofisticato da essere usato così com'è in un'applicazione commerciale. 
     80 
     81Figura 14-5 - Vista `list` del modulo `article` nell'applicazione `backend` 
     82 
     83![Vista list del modulo article in backend](http://www.symfony-project.org/images/book/1_1/F1405.png "Vista list del modulo article in backend") 
     84 
     85Figura 14-6 - Vista `edit` del modulo `article` nell'applicazione `backend` 
     86 
     87![Vista edit del modulo article in backend](http://www.symfony-project.org/images/book/1_1/F1406.png "Vista edit del modulo article in backend") 
     88 
     89### Un'occhiata al codice generato 
     90 
     91Il file del modulo di amministrazione Article, nella cartella `apps/backend/modules/article/`, è vuoto in quanto inizializzato. Il modo migliore per rivedere il codice generato di questo modulo è visualizzare il sorgente della pagina nel browser, per poi quindi controllare il contenuto della cartella `cache/`. 
     92Il Listato 14-4 elenca le azioni e template generate trovate nella cache. 
     93 
     94Listato 14-4 - Elementi dell'amministrazione generata, in `cache/backend/ENV/modules/article/` 
     95 
     96    // In actions/actions.class.php 
     97    create           // Forward a edit 
     98    delete           // Elimina un record 
     99    edit             // Mostra una form per modificare i campi di un record e gestire la submit della form 
     100    index            // Forward a list 
     101    list             // Visualizza la lista di tutti i record di una tabella 
     102    save             // Forward a edit 
     103 
     104    // In templates/ 
     105    _edit_actions.php 
     106    _edit_footer.php 
     107    _edit_form.php 
     108    _edit_header.php 
     109    _edit_messages.php 
     110    _filters.php 
     111    _list.php 
     112    _list_actions.php 
     113    _list_footer.php 
     114    _list_header.php 
     115    _list_messages.php 
     116    _list_td_actions.php 
     117    _list_td_stacked.php 
     118    _list_td_tabular.php 
     119    _list_th_stacked.php 
     120    _list_th_tabular.php 
     121    editSuccess.php 
     122    listSuccess.php 
     123 
     124Ciò mette in evidenza che un modulo di amministrazione generato è composto essenzialmente di due viste, `edit` e `list`. Se dai un'occhiata al codice, lo troverai estremamente modulare, leggibile ed estendibile. 
     125 
     126### Introduzione al file di configurazione generator.yml 
     127 
     128I moduli di amministrazione generati si basano sui parametri che trovano nel file di counfigurazione YAML `generator.yml`. Per vedere la configurazione di default del modulo di amministrazione appena generato, apri il file `generator.yml` situato nella cartella `backend/modules/article/config/generator.yml` e riprodotto nel Listato 14-5. 
     129 
     130Listato 14-5 - Configurazione di default del generatore, in `backend/modules/article/config/generator.yml` 
     131 
     132    generator: 
     133      class:              sfPropelAdminGenerator 
     134      param: 
     135        model_class:      Article 
     136        theme:            default 
     137 
     138Ciò è sufficiente per generare un'amministrazione di base. Tutte le personalizzazioni vanno aggiunte sotto la chiave `param`, dopo la linea `theme` (ciò significa che tutte le linee aggiunte al file `generator.yml` devono essere precedute da minimo quattro spazi bianchi, per essere indentate correttamente). Il Listato 14-6 mostra un tipico `generator.yml` personalizzato. 
     139 
     140Listato 14-6 - Configurazione tipica di un generatore completo 
     141 
     142    generator: 
     143      class:              sfPropelAdminGenerator 
     144      param: 
     145        model_class:      Article 
     146        theme:            default 
     147 
     148        fields: 
     149          author_id:      { name: Article author } 
     150 
     151        list: 
     152          title:          Lista di tutti gli articoli 
     153          display:        [title, author_id, category_id] 
     154          fields: 
     155            published_on: { params: date_format='dd/MM/yy' } 
     156          layout:         stacked 
     157          params:         | 
     158            %%is_published%%<strong>%%=title%%</strong><br /><em>da %%author%% 
     159            in %%category%% (%%published_on%%)</em><p>%%content_summary%%</p> 
     160          filters:        [title, category_id, author_id, is_published] 
     161          max_per_page:   2 
     162 
     163        edit: 
     164          title:          Modifica articolo "%%title%%" 
     165          display: 
     166            "Post":       [title, category_id, content] 
     167            "Workflow":   [author_id, is_published, created_on] 
     168          fields: 
     169            category_id:  { params: disabled=true } 
     170            is_published: { type: plain} 
     171            created_on:   { type: plain, params: date_format='dd/MM/yy' } 
     172            author_id:    { params: size=5 include_custom=>> Scegli un autore << } 
     173            published_on: { credentials:  } 
     174            content:      { params: rich=true tinymce_options=height:150 } 
     175 
     176La sezione seguente spiega in dettaglio i parametri che possono essere utilizzati in questo file di configurazione. 
     177 
     178### Configurazione del generatore 
     179 
     180La configurazione del generatore è molto potente, e ti da la possibilità di modificare l'amministrazione generata in diversi modi. Ma tali funzionalità hanno un prezzo: la sintassi è complessivamente lunga e difficile da imparare, rendendo questo capitolo uno dei più lunghi del libro. Il sito di symfony propone una risorsa alternativa che ti aiuterà ad imparare tale sintassi: il reference card, riprodotto in Figura 14-7. 
     181Scaricalo da [http://www.symfony-project.com/uploads/assets/sfAdminGeneratorRefCard.pdf], e tienilo vicino a te quando leggerai gli esempi seguenti di questo capitolo. 
     182 
     183Gli esempi di questa sezione riguarderanno i moduli di amministrazione di `article` e `comment`, basati sulla classe `Comment`. Crea il secondo con il task `propel:init-admin`: 
     184 
     185    php symfony propel:init-admin backend comment Comment 
     186 
     187Figura 14-7 - La guida di riferimento per il generatore di amministrazione 
     188 
     189![La guida di riferimento per il generatore di amministrazione](http://www.symfony-project.org/images/book/1_1/F1407.png "La guida di riferimento per il generatore di amministrazione") 
     190 
     191### Campi 
     192 
     193Per default, i campi delle viste `list` ed `edit` sono le colonne definite in `schema.yml`. Con `generator.yml`, puoi scegliere quali campi visualizzare, quali nascondere, ed aggiungere campi personalizzati anche se non hanno una corrispondenza nel modello. 
     194 
     195#### Impostazioni dei campi 
     196 
     197Il generatore crea un `field` per ogni colonna del file `schema.yml`. Sotto la chiave `fields`, puoi modificare il modo in cui il campo è visualizzato, formattato, ecc. Ad esempio, le impostazioni del campo mostrati nel Listato 14-7 definiscono per il campo `title` un nome di classe personalizzato ed una textarea, mentre per il campo `content` un suggerimento ed un nome personalizzato. La sezione seguente descriverà in dettaglio ogni parametro. 
     198 
     199Listato 14-7 - Impostare un nome personalizzato per una colonna 
     200 
     201    generator: 
     202      class:              sfPropelAdminGenerator 
     203      param: 
     204        model_class:      Article 
     205        theme:            default 
     206 
     207        fields: 
     208          title:          { name: Article Title, type: textarea_tag, params: class=foo } 
     209          content:        { name: Body, help: Fill in the article body } 
     210 
     211In aggiunta a tale definizione di default per tutte le viste, puoi sovrascrivere le impostazioni di un campo per una vista specifica (`list` e `edit`), come dimostrato dal Listato 14-8. 
     212 
     213Listato 14-8 - Sovrascrivere le impostazioni globali vista per vista 
     214 
     215    generator: 
     216      class:              sfPropelAdminGenerator 
     217      param: 
     218        model_class:      Article 
     219        theme:            default 
     220 
     221        fields: 
     222          title:          { name: Article Title } 
     223          content:        { name: Body } 
     224 
     225        list: 
     226          fields: 
     227            title:        { name: Title } 
     228 
     229        edit: 
     230          fields: 
     231            content:      { name: Body of the article } 
     232 
     233Questo è un principio generale: qualsiasi impostazione per l'intero modulo sotto la chiave `fields` può essere sovrascritta da una specifica vista (`list` ed `edit`) seguente. 
     234 
     235#### Aggiungere campi alla visualizzazione 
     236 
     237I campi definiti nella sezione `fields` possono essere visualizzati, nascosti, ordinati e raggruppati in varie forme per ogni vista. La chiave `display` viene utilizzata a tale scopo. Ad esempio, per riordinare i campi del modulo `comment` usa il codice del listato 14-9. 
     238 
     239Listato 14-9 - Selezionare i campi da visualizzare, in `in modules/comment/config/generator.yml` 
     240 
     241    generator: 
     242      class:              sfPropelAdminGenerator 
     243      param: 
     244        model_class:      Comment 
     245        theme:            default 
     246 
     247        fields: 
     248          article_id:     { name: Article } 
     249          created_at:     { name: Published on } 
     250          content:        { name: Body } 
     251 
     252        list: 
     253          display:        [id, article_id, content] 
     254 
     255        edit: 
     256          display: 
     257            NONE:         [article_id] 
     258            Editable:     [author, content, created_at] 
     259 
     260La `list` mostrerà quindi tre colonne, come in Figura 14-8, e la form di `edit` presenterà quattro campi, assemblati in due gruppi, come in Figura 14-9. 
     261 
     262Figura 14-8 - Selezionare colonne nella vista `list` del modulo `comment` 
     263 
     264![Selezionare colonne nella vista list del modulo comment](http://www.symfony-project.org/images/book/1_1/F1408.png "Selezionare colonne nella vista list del modulo comment") 
     265 
     266Figura 14-9 - Raggruppare campi nella vista `edit` del modulo `comment` 
     267 
     268![Raggruppare campi nella vista edit del modulo comment](http://www.symfony-project.org/images/book/1_1/F1409.png "Raggruppare campi nella vista edit del modulo comment") 
     269 
     270Per cui puoi utilizzare le impostazioni di `display` in due modi: 
     271  * Per selezionare le colonne da visualizzare e l'ordine nel quale devono apparire, metti i campi in un semplice array, come nella precedente vista `list`. 
     272  * Per raggruppare campi, usa un'array associativa con il nome del gruppo come chiave, oppure NONE per un gruppo senza nome. Il valore è di nuovo un'array ordinata di nomi di colonne. 
     273 
     274>**TIP** 
     275>Per default, la chiave primaria non appare in alcuna vista. 
     276 
     277=### Campi personalizzati= 
     278 
     279In pratica, i campi configurati in `generator.yml` non hanno bisogno di corrispondere effettivamente alle colonne dello schema. Se la classe relativa offre un getter personalizzato, puè essere usato come campo per la vista `list`; se c'è un getter e/o un setter, può essere usato per la `edit`. Ad esempio, puoi estendere il modello di `Article` con un metodo `getNbComments()` simile a quello del Listato 14-10. 
     280 
     281Listato 14-10 - Aggiungere un getter nel modello, in `lib/model/Article.class.php` 
     282 
     283    [php] 
     284    public function getNbComments() 
     285    { 
     286      return $this->countComments(); 
     287    } 
     288 
     289Dopodiché `nb_comments` è disponibile come campo nel modulo generato (nota che il getter utilizza una versione camelCase del nome del campo), come nel Listato 14-11. 
     290 
     291Listato 14-11 - Getter personalizzati forniscono colonne aggiuntive nei moduli di amministrazione, in `backend/modules/article/config/generator.yml` 
     292 
     293    [php] 
     294    generator: 
     295      class:              sfPropelAdminGenerator 
     296      param: 
     297        model_class:      Article 
     298        theme:            default 
     299 
     300        list: 
     301          display:        [id, title, nb_comments, created_at] 
     302 
     303La risultante vista `list` del modulo `article`  mostrata in Figura 14-10. 
     304 
     305Figura 14-10 - Campo personalizzato nella vista `list` del modulo `article` 
     306 
     307![Campo personalizzato nella vista list del modulo article](http://www.symfony-project.org/images/book/1_1/F1410.png "Campo personalizzato nella vista list del modulo article") 
     308 
     309Campi personalizzati possono anche restituire codice HTML per visualizzare qualcosa di più di dati grezzi. Ad esempio, puoi estendere la classe `Comment` con un metodo `getArticleLink()` come mostrato nel Listato 14-12. 
     310 
     311Listato 14-12 - Aggiungere un getter personalizzato che restituisce HTML, in `lib/model/Comment.class.php` 
     312 
     313    [php] 
     314    public function getArticleLink() 
     315    { 
     316      return link_to($this->getArticle()->getTitle(), 'article/edit?id='.$this->getArticleId()); 
     317    } 
     318 
     319Puoi usare questo nuovo getter come campo personalizzato nella vista `comment/list` con la stessa sintassi del Listato 14-11. Vedi l'esempio nel Listato 14-13, ed il risultato in Figura 14-11, dove il codice HTML in output dal getter (un link all'articolo) viene mostrato nella seconda colonna al posto della chiave primaria dell'articolo. 
     320 
     321Listato 14-13 - Getter personalizzati che restituiscono HTML possono anche essere usati come colonne aggiuntive, in `modules/comment/config/generator.yml` 
     322 
     323    generator: 
     324      class:              sfPropelAdminGenerator 
     325      param: 
     326        model_class:      Comment 
     327        theme:            default 
     328 
     329        list: 
     330          display:        [id, article_link, content] 
     331 
     332Figura 14-11 - Campo personalizzato nella vista `list` del modulo `comment` 
     333 
     334![Campo personalizzato nella vista list del modulo comment](http://www.symfony-project.org/images/book/1_1/F1411.png "Campo personalizzato nella vista list del modulo comment") 
     335 
     336#### Campi partial 
     337 
     338Il codice situato nel modello deve essere indipendente dalla presentazione. L'esempio precedente del metodo `getArticleLink()` non rispetta il principio della separazione dei livelli, in quanto codice della vista compare nel modello. Per raggiungere lo stesso scopo in modo corretto, dovresti mettere il codice che stampa l'HTML per un campo personalizzato in un partial. Fortunatamente, il generatore di amministrazione ti permette di specificare il nome di un campo preceduto da un prefisso con un trattino basso. In questo caso, il file `generator.yml` del Listato 14-13 verrebbe modificato come nel Listato 14-14. 
     339 
     340Listato 14-14 - I partial possono essere usati come colonne aggiuntive - usa il `_prefisso` 
     341 
     342    list: 
     343        display:        [id, _article_link, created_at] 
     344 
     345Per funzionare, il partial `_article_link.php` deve essere posizionato nella cartella `modules/comment/templates/`, come nel Listato 14-15. 
     346 
     347Listato 14-15 - Esempio di partial per la vista `list`, in `modules/comment/templates/_article_link.php` 
     348 
     349    [php] 
     350    <?php echo link_to($comment->getArticle()->getTitle(), 'article/edit?id='.$comment->getArticleId()) ?> 
     351 
     352Nota che il template partial di un campo partial ha accesso all'oggetto corrente tramite una variabile che ha lo stesso nome della classe (in questo esempio `$comment`). Ad esempio, per un modulo costruito per una classe chiamata `UserGroup`, il partial avrà accesso all'oggetto corrente tramite la variabile `$user_group`. 
     353 
     354Il risultato è lo stesso della Figura 14-11, a parte che stavolta viene rispettata la separazione dei livelli. Se ti abitui a tale meccanismo, avrai applicazioni molto più manutenibili. 
     355 
     356Se avessi bisogno di personalizzare parametri per un partial, fai lo stesso come per i campi normali, sotto la chiave `field`. Semplicemente non includere il trattino basso iniziale, come nell'esempio del Listato 14-16. 
     357 
     358Listato 14-16 - Le proprietà di un partial possono essere personalizzate sotto la chiave `fields` 
     359 
     360    fields: 
     361      article_link:   { name: Article } 
     362 
     363Se il tuo partial contiene una logica complicata, probabilmente lo vorrai sostituire con un component. Cambia il prefisso da `_` a `~` ed il gioco è fatto, come puoi vedere dal Listato 14-17. 
     364 
     365Listato 14-17 - I componenti possono essere usati come colonne aggiuntive - usa il `~prefisso` 
     366 
     367    ... 
     368    list: 
     369      display:        [id, ~article_link, created_at] 
     370 
     371Nel template generato, questo sfocierà in una chiamata al component `articleLink` del modulo corrente. 
     372 
     373>**NOTE** 
     374>Campi personalizzati e partial possono essere usati nelle viste `list` ed `edit`, e per i filtri. Se usi lo stesso partial per diverse viste, il contesto ('list', 'edit', o 'filter') è memorizzato nella variabile `$type`. 
     375 
     376### Personalizzazione della vista 
     377 
     378Per cambiare il modo in cui appaiono le viste `edit` e `list` potresti essere tentato di cambiarne i template. Ma dato che esse vengono generate, non è una bella idea. Invece dovresti usare il file di configurazione `generator.yml` in quanto può fare quasi tutto quel che ti serve senza sacrificare la modularità. 
     379 
     380#### Cambiare il titolo della vista 
     381 
     382In aggiunta ai campi personalizzati, le pagine `edit` e `list` possono avere un titolo di pagina anch'esso personalizzato. Ad esempio, se tu volessi cambiare il titolo della vista `articles`, dovresti fare come nel Listato 14-18. Il risultato è illustrato in Figura 14-12. 
     383 
     384Listato 14-18 - Impostare un titolo personalizzato per ogni vista, in `backend/modules/article/config/generator.yml` 
     385 
     386    list: 
     387      title:          List of Articles 
     388      ... 
     389 
     390    edit: 
     391      title:          Body of article %%title%% 
     392      display:        [content] 
     393 
     394Figura 14-12 - Titolo della vista `edit` del modulo `article` 
     395 
     396![Titolo della vista edit del modulo article](http://www.symfony-project.org/images/book/1_1/F1412.png "Titolo della vista edit del modulo article") 
     397 
     398Dato che i titoli di default usano il nome della classe, vanno abbastanza bene (sempre che nel tuo modello tu abbia usato nomi espliciti per le classi). 
     399 
     400>**TIP** 
     401>Nelle stringhe di `generator.yml`, il valore di un campo può essere acceduto tramite il nome del campo tra %%. 
     402 
     403#### Aggiungere tooltip 
     404 
     405Nelle viste `list` ed `edit`, puoi aggiungere tooltip per aiutare a descrivere i campi visualizzati. Ad esempio, per aggiungere un tooltip al campo `article_id` della vista `edit` del modulo `comment`, aggiungi una prorietà `help` nella definizione `fields` come nel Listato 14-19. Il risultato è mostrato in Figura 14-13. 
     406 
     407Listato 14-19 - Impostare un tooltip nella vista `edit`, in `modules/comment/config/generator.yml` 
     408 
     409    edit: 
     410      fields: 
     411        ... 
     412        article_id:   { help: The current comment relates to this article } 
     413 
     414Figura 14-13 - Tooltip nella vista `edit` del modulo `comment` 
     415 
     416![Tooltip nella vista edit del modulo comment](http://www.symfony-project.org/images/book/1_1/F1413.png "Tooltip nella vista edit del modulo comment") 
     417 
     418Nella vista `list`, i tooltip vengono visualizzati nella colonna `header`; nella vista `edit`, essi appaiono sotto l'input. 
     419 
     420#### Modificare il formato delle date 
     421 
     422Le date possono essere visualizzate secondo un formato personalizzato, se utilizzi il parametro `date_format`, come mostrato dal Listato 14-20. 
     423 
     424Listato 14-20 - Formattare una data nella vista `list` 
     425 
     426    list: 
     427      fields: 
     428        created_at:         { name: Published, params: date_format='dd/MM' } 
     429 
     430Esso utilizza gli stessi parametri dell'helper `format_date()` visto nel capitolo precedente. 
     431 
     432>**SIDEBAR** 
     433>I template di amministrazione sono pronti per i18n 
     434>Tutti i testi dei template generati sono internazionalizzati automaticamente (ovvero stampati tramite l'helper `__()`). Ciò significa che puoi tradurre un'amministrazione generata semplicemente inserendo i testi nel file XLIFF dentro la cartella `apps/frontend/i18n/`, come descritto nel capitolo precedente. 
     435 
     436### Personalizzazioni specifiche per la vista list 
     437 
     438La vista `list` può visualizzare i dettagli di un record in una tabella, oppure tutti in una linea. Inoltre contiene funzionalità di paginazione, filtri ed ordinamento. Tali funzionalità possono essere alterate tramite il file di configurazione, come illustrato nelle sezioni seguenti. 
     439 
     440 
     441#### Cambiare il layout 
     442 
     443Per default, il link per passare dalla `list` alla `edit` viene inserito sulla chiave primaria. Se dai un'occhiata indietro alla Figura 14-11, vedrai che la colonna `id` non solo rappresenta la chiave primaria di ogni commento, ma è anche cliccabile per passare alla vista `edit`. 
     444 
     445Se preferisci avere tale link su un'altra colonna, metti il prefisso = su tale colonna sotto la chiave `display`. Il Listato 14-21 mostra come rimuovere la colonna `id` dalla vista `list` e mettere il link sul campo `content`. Controlla la Figura 14-14 per una schermata. 
     446 
     447Listato 14-21 - Spostare il link alla vista `edit` nella vista `list`, in `modules/comment/config/generator.yml` 
     448 
     449    list: 
     450      display:    [article_link, =content] 
     451 
     452Figura 14-14 - Spostare il link alla vista `edit` su un'altra colonna, nella vista `list` del modulo `comment` 
     453 
     454![Spostare il link alla vista edit su un'altra colonna, nella vista list del modulo comment](http://www.symfony-project.org/images/book/1_1/F1414.png "Spostare il link alla vista edit su un'altra colonna, nella vista list del modulo comment") 
     455 
     456Per default, la vista `list` usa un layout tabulare, dove i campi appaiono come colonne, come visto precedentemente. Ma puoi anche usare il layout `stacked` e concatenare i campi in una singola stringa per tutta la lunghezza della tabella. Se scegli tale layout, devi impostare nella chiave `params` il pattern che definisce come la stringa deve essere composta. Ad esempio, il Listato 14-22 definisce un layout `stacked` per la vista `list` del modulo `comment`. Il risultato appare nella Figura 14-15. 
     457 
     458Listato 14-22 - Utilizzare il layout `stacked` nella vista `list`, in `modules/comment/config/generator.yml` 
     459 
     460    list: 
     461      layout:  stacked 
     462      params:  | 
     463        %%=content%% <br /> 
     464        (sent by %%author%% on %%created_at%% about %%article_link%%) 
     465      display:  [created_at, author, content] 
     466 
     467Figura 14-15 - Layout `stacked` per la vista `list` del modulo `comment` 
     468 
     469![Layout stacked per la vista list del modulo comment](http://www.symfony-project.org/images/book/1_1/F1415.png "Layout stacked per la vista list del modulo comment") 
     470 
     471Nota che il layout `tabular` si aspetta un'array di campi sotto la chiave `display`, ma quello `stacked` usa la chiave `params` per il codice HTML per ogni record generato. Comunque, l'array `display` è usato nel layout `stacked` per determinare quali colonne sono disponibili per l'ordinamento interattivo. 
     472 
     473#### Filtrare i risultati 
     474 
     475Nella vista `list` puoi aggiungere un insieme di interazioni per i filtri. Tramite essi, l'utente può visualizzare meno risultati e trovare così quelli che cerca più velocemente. Configura il filtri sotto la chiave `filters`, con un'array di nomi di campi. Ad esempio, per avere un risultato come quello della Figura 14-16, aggiungi un filtro sui campi `article_id`, `author` e `created_at`, come mostrato nel Listato 14-23. Per fare ciò, avrai anche bisogno di aggiungere un metodo `__toString()` alla classe `Article` (che restituisca, ad esempio, il titolo dell'articolo). 
     476 
     477Listato 14-23 - Impostare filtri nella vista `list`, in `modules/comment/config/generator.yml` 
     478 
     479    list: 
     480      filters: [article_id, author, created_at] 
     481      layout:  stacked 
     482      params:  | 
     483        %%=content%% <br /> 
     484        (sent by %%author%% on %%created_at%% about %%article_link%%) 
     485      display:  [created_at, author, content] 
     486 
     487Figura 14-16 - Filtri nella vista `list` del modulo `comment` 
     488 
     489![Filtri nella vista list del modulo comment](http://www.symfony-project.org/images/book/1_1/F1416.png "Filtri nella vista list del modulo comment") 
     490 
     491I filtri visualizzati da symfony dipendono dal tipo di colonna: 
     492  * Per colonne di testo (come il campo `author` del modulo `comment`), il filtro è una casella di testo che permette ricerche con wildcard (*). 
     493  * Per le chiavi importate (come il campo `article_id` del modulo `comment`), il filtro è un menu a tendina con i record della tabella relativa. Come per l'helper `object_select_tag()`, le options del menu a tendina sono le stringhe restituite dal metodo `__toString()` della classe relativa. 
     494  * Per le date (come il campo `created_at` del modulo `comment`), il filtro è una coppia di tag date rich (casella di testo e widget calendario) che permettono la selezione di intervalli di tempo. 
     495  * Per colonne booleane, il filtro è un menu a tendina con le opzioni `true`, `false` e `true or false` (quest'ultimo valore reinizializza il filtro). 
     496 
     497Esattamente come usi campi partial nelle liste, puoi creare filtri partial per averne un non gestito automaticamente da symfony. Ad esempio, immagina un campo `state` che possa contenere solo due valori (`open` e `closed`), ma per qualche ragione memorizzi il valore direttamente nel campo invece che in una tabella. Un semplice filtro su questo campo (di tipo `string`) sarebbe una ricerca di testo, ma probabilmente tu vorresti un menu a tendina. Questo diventa semplice da realizzare con un filtro partial. Vedi il Listato 14-24 per un esempio di implementazione. 
     498 
     499Listato 14-24 - Utilizzare un filtro partial 
     500 
     501    // Definizione del partial, in templates/_state.php 
     502    <?php echo select_tag('filters[state]', options_for_select(array( 
     503      '' => '', 
     504      'open' => 'open', 
     505      'closed' => 'closed', 
     506    ), isset($filters['state']) ? $filters['state'] : '')) ?> 
     507      
     508    // Aggiunta del partial nella lista dei filtri, in config/generator.yml 
     509        list: 
     510          filters:        [date, _state] 
     511 
     512Nota che il partial ha accesso alla variabile `$filters`, utile per recuperare il valore corrente del filtro. 
     513 
     514C'è un'ultima opzione che può essere molto utile nella ricerca di valori vuoti. Immagina di voler filtrare la lista dei commenti per visualizzare solo quelli senza autore. Il problema è che se lasci il filtro author vuoto, verrà semplicemente ignorato. La soluzione è impostare il campo `filter_is_empty` a `true`, come nel listato 14-25, ed il filtro mostrerà un checkbox addizionale che ti permetterà di cercare valori vuoti, come mostrato in Figura 14-17. 
     515 
     516Listato 14-25 - Aggiungere un filtro per valori vuoti sul campo `author` nella vista `list` 
     517 
     518    list: 
     519      fields: 
     520        author:   { filter_is_empty: true } 
     521      filters:    [article_id, author, created_at] 
     522 
     523Figura 14-17 - Permettere il filtro di valori vuoti 
     524 
     525![Permettere il filtro di valori vuoti](http://www.symfony-project.org/images/book/1_1/F1417.png "Permettere il filtro di valori vuoti") 
     526 
     527#### Ordinamento della lista 
     528 
     529Nella vista `list`, gli header della tabella sono link che possono essere usati per riordinare la lista, come mostrato in Figura 14-18. Tali header vengono mostrati in entrambi i layout, `tabular` e `stacked`. Cliccarne uno significa ricaricare la pagina con un parametro `sort` che ordina la lista di conseguenza. 
     530 
     531Figura 14-18 - Gli header nella tabella della vista `list` controllano l'ordinamento 
     532 
     533![Gli header nella tabella della vista list controllano l'ordinamento](http://www.symfony-project.org/images/book/1_1/F1418.png "Gli header nella tabella della vista list controllano l'ordinamento") 
     534 
     535Puoi riutilizzare la sintassi per indirizzare un'elenco già ordinato secondo una colonna: 
     536 
     537    <?php echo link_to('Comment list by date', 'comment/list?sort=created_at&type=desc' ) ?> 
     538 
     539Puoi infine definire un ordinamento di default direttamente nel file di configurazione `generator.yml`. La sintassi è mostrata nell'esempio del Listato 14-26. 
     540 
     541Listato 14-26 - Impostare un ordinamento di default nella vista `list` 
     542 
     543    list: 
     544      sort:   created_at 
     545      # Sintassi alternativa, per specificare un ordine 
     546      sort:   [created_at, desc] 
     547 
     548>**NOTE** 
     549>Solo i campi corrispondenti a colonne effettive sono trasformati in controlli di ordinamento, non i partial o i campi personalizzati. 
     550 
     551#### Personalizzare la paginazione 
     552 
     553Le amministrazioni generate gestiscono bene anche tabelle molto grandi, perché per default utilizzano la paginazione. Quando il numero effettivo di righe eccede il numero massimo di righe per pagina, i controlli della paginazione appaiono nell'angolo in basso a destra. Ad esempio, la Figura 14-19 mostra la lista dei commenti con sei commenti di test nella tabella ma un limite di cinque per pagina. La paginazione assicura buone prestazioni, in quanto solo le righe da visualizzare sono effettivamente recuperate dal database, ed una buona usabilità, perché anche tabelle con milioni di righe possono essere gestite da un modulo di amministrazione. 
     554 
     555Figura 14-19 - Appaiono i controlli di paginazione in elenchi lunghi 
     556 
     557![Appaiono i controlli di paginazione in elenchi lunghi](http://www.symfony-project.org/images/book/1_1/F1419.png "Appaiono i controlli di paginazione in elenchi lunghi") 
     558 
     559Puoi personalizzare il numero di record da visualizzare per pagina tramite il parametro `max_per_page`: 
     560 
     561    list: 
     562      max_per_page:   5 
     563 
     564#### Usare un join per velocizzare l'invio delle pagine 
     565 
     566Per default, un generatore di administration usa una semplice `doSelect()` per recuperare una lista di record dal db. Ma se gli oggetti della lista hanno delle relazioni, il numero di query necessarie alla sua costruzione potrebbe aumentare velocemente. Ad esempio, se vuoi vedere il nome dell'articolo in una lista di commenti, necessaria una query addizionale per ogni record per trovare il relativo `Article`. Per cui potresti voler forzare il pager ad utilizzare il metodo `doSelectJoinXXX()` per ottimizzare il numero di query. Ciò può essere specificato tramite il parametro `peer_method`. 
     567 
     568    list: 
     569      peer_method:   doSelectJoinArticle 
     570 
     571Il Capitolo 18 spiega più estensivamente il concetto di join. 
     572 
     573### Personalizzazioni specifiche per la vista edit 
     574 
     575Nella vista `edit`, l'utente può modificare il valore di ogni colonna per un dato record. Symfony determina il tipo di input da visualizzare secondo il data type della colonna. Quindi genera un helper `object_*_tag()`, e gli passa l'oggetto e la proprietà da modificare. Ad esempio, se nella configurazione della vista `edit` per l'articolo è specificato che l'utente può modificare il campo `title`: 
     576 
     577    edit: 
     578      display: [title, ...] 
     579 
     580allora nella pagina `edit` verrà visualizzato una casella di testo per la modifica di `title`, in quanto nello schema esso è definito di tipo `varchar`. 
     581 
     582    [php] 
     583    <?php echo object_input_tag($article, 'getTitle') ?> 
     584 
     585 
     586#### Cambiare il tipo di input 
     587 
     588Le regole di conversione type-to-field di default sono le seguenti: 
     589  * Una colonna definita come `integer, float, char, varchar(size)` appare nella vista `edit` come un `object_input_tag()`. 
     590  * Una colonna definita come `longvarchar` appare come `object_textarea_tag()`. 
     591  * Una chiave importata appare come `object_select_tag()`. 
     592  * Una colonna definita come `boolean` appare come `object_checkbox_tag()`. 
     593  * Una colonna definita come `timestamp` appare come `object_input_date_tag()`. 
     594 
     595Potresti voler fare l'override di queste regole per specificare un tipo di input personalizzato per un certo campo. Per fare ciò, imposta il parametro `type` ad uno specifico nome di helper nella definizione `fields`. Come per le opzioni del `object_*_tag()` generato, le puoi cambiare tramite il parametro `params`. Un esempio nel Listato 14-27. 
     596 
     597Listato 14-27 - Impostare un tipo di input personalizzato per la vista `edit` 
     598 
     599    generator: 
     600      class:              sfPropelAdminGenerator 
     601      param: 
     602        model_class:      Comment 
     603        theme:            default 
     604 
     605        edit: 
     606          fields: 
     607                          ## Drop the input, just display plain text 
     608            id:           { type: plain } 
     609                          ## The input is not editable 
     610            author:       { params: disabled=true } 
     611                          ## The input is a textarea (object_textarea_tag) 
     612            content:      { type: textarea_tag, params: rich=true css=user.css tinymce_options=width:330 } 
     613                          ## The input is a select (object_select_tag) 
     614            article_id:   { params: include_custom=Choose an article } 
     615             ... 
     616 
     617I parametri `params` vengono passati come opzioni al `object_*_tag()` generato. Ad esempio, la definizione di `params` per il precedente `article_id` produce nel template: 
     618 
     619    [php] 
     620    <?php echo object_select_tag($comment, 'getArticleId', 'related_class=Article', 'include_custom=Choose an article') ?> 
     621 
     622Ciò significa che tutte le opzioni normalmente disponibili negli helper delle form possono essere personalizzate nella vista `edit`. 
     623 
     624#### Gestire campi partial 
     625 
     626I campi partial possono essere usati nella vista `edit` proprio come nella `list`. La differenza sta nel fatto che devi gestire manualmente, nell'azione, l'aggiornamento della colonna secondo il valore del parametro di richiesta spedito dal partial. Symfony sa come gestire i campi normali (corrispondenti alle colonne effettive), ma non può immaginare come gestire input che tu potresti inserire in partial. 
     627 
     628Ad esempio, immagina un modulo di amministrazione per una classe `User` dove sono disponibili i campi `id, nickname`, e `password`. L'amministratore del sito deve poter cambiare la password di un utente ma la vista `edit` non deve visualizzarne il valore per motivi di sicurezza. Invece, la form deve mostrare una casella di testo vuota che l'amministratore può riempire per cambiare la password. Le impostazioni per il generatore per tale tipo di vista sono simili a quelli del Listato 14-28. 
     629 
     630Listato 14-28 - Includere un partial nella lista `edit` 
     631 
     632    edit: 
     633      display:        [id, nickname, _newpassword] 
     634      fields: 
     635        newpassword:  { name: Password, help: Enter a password to change it, leave the field blank to keep the current one } 
     636 
     637Il partial `templates/_newpassword.php` contiente qualcosa tipo 
     638 
     639    [php] 
     640    <?php echo input_password_tag('newpassword', '') ?> 
     641 
     642Nota che questo partial utilizza un helper delle form normale, non un object, in quanto non è desiderabile recuperare il valore della password dall'oggetto `User` corrente per popolare una casella di testo.  
     643 
     644Ora, per utilizzare il valore di tale input per poter aggiornare l'oggetto nell'azione, ne devi estendere il metodo `updateUserFromRequest()`. Per fare ciò, crea un metodo con lo stesso nome nella classe dell'azione, come mostrato nel Listato 14-29. 
     645 
     646Listato 14-29 - Gestire un partial nell'azione, in `modules/user/actions/actions.class.php` 
     647 
     648    [php] 
     649    class userActions extends sfActions 
     650    { 
     651      protected function updateUserFromRequest() 
     652      { 
     653        // Handle the input of the partial field 
     654        $password = $this->getRequest()->getParameter('newpassword'); 
     655      
     656        if ($password) 
     657        { 
     658          $this->user->setPassword($password); 
     659        } 
     660      
     661        // Let symfony handle the other fields 
     662        parent::updateUserFromRequest(); 
     663      } 
     664    } 
     665 
     666>**NOTE** 
     667>Nel mondo reale, una vista `user/edit` contiene due campi per la password, il secondo dei quali deve contenere lo stesso valore del primo per controllare che non ci siano errori di digitazione. In pratica, come hai visto nel Capitolo 10, questo viene fatto tramite validazione. Le amministrazioni generate beneficiano dello stesso meccanismo come gli altri moduli. 
     668 
     669### Gestire chiavi importate 
     670 
     671Se il tuo schema definisce relazioni tra le tabelle, i moduli di amministrazione generati se ne avvantaggiano offrendo controlli automatizzati, semplificando così enormemente il sistema di gestione delle relazioni. 
     672 
     673#### Relazioni uno-a-molti 
     674 
     675Il generatore di amministrazioni si occupa di relazioni 1-n. Come illustrato precedentemente nella Figura 14-1, la tabella `blog_comment` legata a `blog_article` tramite il campo `article_id`. Se inizializzi il modulo della classe `Comment` con il generatore di amministrazioni, l'azione `comment/edit` visualizzerà automaticamente `article_id` come un menu a tendina con gli ID dei record disponibili della tabella `blog_article` (controlla di nuovo la Figura 14-9 per un esempio). 
     676 
     677Inoltre, se definisci un metodo `__toString()` nell'oggetto `Article`, la tendina mostrerà nelle proprie opzioni invece delle chiavi primarie il valore restituito da tale metodo. 
     678 
     679Se hai bisogno di mostrare la lista dei commenti relativi ad un articolo nel modulo `article` (relazione n-1), avrai bisogno di personalizzare un pochino il modulo tramite un partial. 
     680 
     681### Relazioni molti-a-molti 
     682 
     683Symfony si occupa anche delle relazioni n-n, ma dato che non le puoi definire nello schema, devi aggiungere qualche parametro nel file `generator.yml`. 
     684 
     685L'implementazione delle relazioni n-n richiede una tabella intermedia. Se ad esempio ci fosse una relazione n-n fra le tabelle `blog_article` e `blog_author` (un articolo può essere scritto da più di un autore e, ovviamente, un autore può scrivere più articoli), il tuo database avrà una tabella `blog_article_author` o simile, come mostrato in Figura 14-20. 
     686 
     687Figura 14-20 - Implementazione delle relazioni molti-a-molti 
     688 
     689![Implementazione delle relazioni molti-a-molti](http://www.symfony-project.org/images/book/1_1/F1420.png "Implementazione delle relazioni molti-a-molti") 
     690 
     691Il modello avrà quindi una classe chiamata `ArticleAuthor`, e questa è la sola cosa di cui il generatore di amministrazioni abbia bisogno; ma devi passarglielo come parametro `through_class`. 
     692 
     693Ad esempio, in un modulo generato basato sulla classe `Article`, puoi aggiungere un campo per creare una relazione n-n con la classe `Author` se scrivi il file `generator.yml` come nel Listato 14-30. 
     694 
     695Listato 14-30 - Gestire relazioni molti-a-molti tramite il parametro `through_class` 
     696 
     697    edit: 
     698      fields: 
     699        article_author: { type: admin_double_list, params: through_class=ArticleAuthor } 
     700 
     701Tale campo gestisce i collegamenti tra gli oggetti esistenti, per cui un menu a tendina non è sufficiente. Devi usare un tipo di input speciale in questo caso. 
     702Symfony offre tre widget per aiutare a mettere in relazione i membri di due liste (illustrati nella Figura 14-21): 
     703  * Un `admin_double_list` è un insieme di due menu a tendina espansi, entrambi con pulsanti per spostare elementi dalla prima lista (disponibili) alla seconda (selezionati). 
     704  * Un `admin_select_list` è un menu a tendina multiplo, in cui puoi selezionare più di un elemento. 
     705  * Un `admin_check_list` è una lista di checkbox. 
     706 
     707Figura 14-21 - Controlli disponibili per relazioni molti-a-molti 
     708 
     709![Controlli disponibili per relazioni molti-a-molti](http://www.symfony-project.org/images/book/1_1/F1421.png "Controlli disponibili per relazioni molti-a-molti") 
     710 
     711### Aggiungere interazioni 
     712 
     713I moduli di amministrazione permettono le normali operazioni CRUD, ma puoi anche aggiungere le tue personali interazioni o limitazioni. Ad esempio, l'interazione definita nel Listato 14-31 fornisce accesso a tutte le azioni CRUD di default sul modulo `article`. 
     714 
     715Listato 14-31 - Definire interazioni per ogni vista, in `backend/modules/article/config/generator.yml` 
     716 
     717    list: 
     718      title:          List of Articles 
     719      object_actions: 
     720        _edit:         ~ 
     721        _delete:       ~ 
     722      batch_actions: 
     723        _delete:       ~ 
     724      actions: 
     725        _create:       ~ 
     726 
     727    edit: 
     728      title:          Body of article %%title%% 
     729      actions: 
     730        _list:         ~ 
     731        _save:         ~ 
     732        _save_and_add: ~ 
     733        _delete:       ~ 
     734 
     735In una vista `list` ci sono tre impostazioni di azione: la lista delle azioni disponibili per ogni oggetto (`object_actions`), le azioni disponibili per un insieme di oggetti (`batch_actions`), quelle per l'intera pagina (`actions`). L'effetto delle interazioni definite nel Listato 14-31 è mostrato in Figura 14-22. Ogni linea mostra un pulsante per modificare il record ed uno per eliminarlo. Alla ifne della pagina, un pulsante permette di crearne di nuovi. 
     736 
     737Figura 14-22 - Interazioni nella vista `list` 
     738 
     739![Interazioni nella vista list](http://www.symfony-project.org/images/book/1_1/F1422.png "Interazioni nella vista list") 
     740 
     741In una vista `edit`, dato che c'è un solo record da modificare, è disponibile un solo set di azioni da definire (`under_actions`). L'effetto delle interazioni `edit` definite nel Listato 14-31 è mostrato in Figura 14-23. Entrambe le azioni `save` e `save_and_add` salvano il record corrente; a differenza è che la prima mostra i dati salvati, la seconda campi vuoti per aggiungere un nuovo record. Tale azione risulterà molto utile quando devi aggiungere molti record in rapida successione. Riguardo la posizione del pulsante `delete`, esso è distanziato dagli altri perchè non venga cliccato per errore. 
     742 
     743I nomi delle interazioni che cominciano con un underscore (_) indicano a symfony di usare le icone ed azioni di default corrispondenti; il generatore di amministrazioni capisce `_edit, _delete, _create, _list, _save, _save_and_add`, e `_create`. 
     744 
     745Figura 14-23 - Interazioni nella vista `edit` 
     746 
     747![Interazioni nella vista edit](http://www.symfony-project.org/images/book/1_1/F1423.png "Interazioni nella vista edit") 
     748 
     749Ma puoi anche aggiungere un'interazione personalizzata, nel qual caso devi specificare un nome che non cominci col trattino basso, ed un'azione target nel modulo corrente, come nel Listato 14-32. 
     750 
     751Listato 14-32 - Definire un'interazione personalizzata 
     752 
     753    list: 
     754      title:          List of Articles 
     755      object_actions: 
     756        _edit:        - 
     757        _delete:      - 
     758        addcomment:   { name: Add a comment, action: addComment, icon: backend/addcomment.png } 
     759 
     760Ogni articolo della lista visualizzerà ora un pulsante `addcomment.png`, come mostrato in Figura 14-24. Cliccandolo viene chiamata l'azione `addComment` del modulo corrente. La chiave primaria dell'oggetto corrente viene aggiunta automaticamente ai parametri di richiesta. 
     761 
     762Figura 14-24 - Interazione personalizzata nella vista `list` 
     763 
     764![Interazione personalizzata nella vista list](http://www.symfony-project.org/images/book/1_1/F1424.png "Interazione personalizzata nella vista list") 
     765 
     766L'azione `addComment` può essere implementata come nel Listato 14-33. 
     767 
     768Listato 14-33 - Implementare l'azione dell'interazione personalizzata, in `actions/actions.class.php` 
     769 
     770    [php] 
     771    public function executeAddComment($request) 
     772    { 
     773      $comment = new Comment(); 
     774      $comment->setArticleId($request->getParameter('id')); 
     775      $comment->save(); 
     776      
     777      $this->redirect('comment/edit?id='.$comment->getId()); 
     778    } 
     779 
     780Le azioni batch ricevono un'array di chiavi primarie dei record selezionati nel parametro di richiesta `sf_admin_batch_selection`. 
     781 
     782Un'ultima cosa a proposito delle azioni: se vuoi sopprimere completamente le azioni per una categoria, usa una lista vuota, come nel Listato 14-34. 
     783 
     784Listato 14-34 - Rimuovere tutte le azioni nella vista `list` 
     785 
     786    list: 
     787      title:          List of Articles 
     788      actions:        {} 
     789 
     790### Validazione delle form 
     791 
     792Se dai un'occhiata al template generato `_edit_form.php` nella cartella `cache/` del tuo progetto, vedrai che i nomi dei campi della form usano una convenzione speciale. In una vista `edit` generata, i nomi dei campi sono la concatenazione del nome del modulo e del campo tra parentesi quadre. 
     793 
     794Ad esempio, se la vista `edit` per il modulo `article` ha un campo `title`, il template sarà come quello del Listato 14-35 ed il campo sarà identificato come `article[title]`. 
     795 
     796Listato 14-35 - Sintassi dei nomi degli input generati 
     797 
     798    // generator.yml 
     799    generator: 
     800      class:              sfPropelAdminGenerator 
     801      param: 
     802        model_class:      Article 
     803        theme:            default 
     804        edit: 
     805          display: [title] 
     806 
     807    // Resulting _edit_form.php template 
     808    <?php echo object_input_tag($article, 'getTitle', array('control_name' => 'article[title]')) ?> 
     809 
     810    // Resulting HTML 
     811    <input type="text" name="article[title]" id="article[title]" value="My Title" /> 
     812 
     813Ciò ha molti vantaggi durante il processo di gestione interna della form. Come spiegato nel Capitolo 10, ciò ha anche come conseguenza l'aggiunta di un pizzico di complessità nella configurazione della validazione, per cui devi sostituire le parentesi quadre con le graffe nella definizione `fields`. Inoltre, quando usi il nome di un campo come parametro per la validazione, lo devi specificare come appare nel codice HTML generato (ovvero con le parentesi quadre ma tra doppi apici). Consulta il Listato 14-36 per dettagli sulla sintassi speciale della validazione per form generate. 
     814 
     815Listato 14-36 - Sintassi per la validazione di form generate nelle amministrazioni 
     816 
     817    ## Sostituzione delle parentesi quadre con le graffe nella definizione fields 
     818    fields: 
     819      article{title}: 
     820        required: 
     821          msg: You must provide a title 
     822        ## Per i parametri di validazione usa i doppi apici 
     823        sfCompareValidator: 
     824          check:        "user[newpassword]" 
     825          compare_error: The password confirmation does not match the password. 
     826 
     827### Limitare le azioni dell'utente utilizzando credenziali 
     828 
     829Per un dato modulo di amministrazione, i campi disponibili e le interazioni possono variare a seconda delle credenziali dell'utente corrente (consulta il Capitolo 6 per una descrizione delle funzionalità di sicurezza di symfony). 
     830 
     831I campi nel generatore possono avere un parametro `credentials` in modo da apparire solo agli utenti che hanno le credenziali corrette. Ciò funziona per le viste `list` ed `edit`. Inoltre, il generatore può anche nascondere interazioni secondo le credenziali. Il Listato 14-37 mostra tali funzionalità. 
     832 
     833Listato 14-37 - Utilizzo delle credenziali in `generator.yml` 
     834 
     835    ## La colonna id viene mostrata solo ad utenti con credenziali admin 
     836        list: 
     837          title:          List of Articles 
     838          layout:         tabular 
     839          display:        [id, =title, content, nb_comments] 
     840          fields: 
     841            id:           { credentials: [admin] } 
     842 
     843    ## L'interazione addcomment è limitata agli utenti con credenziali admin 
     844        list: 
     845          title:          List of Articles 
     846          object_actions: 
     847            _edit:        - 
     848            _delete:      - 
     849            addcomment:   { credentials: [admin], name: Add a comment, action: addComment, icon: backend/addcomment.png } 
     850 
     851Modificare la presentazione dei moduli generati 
     852----------------------------------------------- 
     853 
     854Puoi modificare la presentazione dei moduli generati in modo che rispetti lo stile dell'applicazione, non solo applicando il tuo stylesheet ma anche facendo l'override dei template di default. 
     855 
     856### Utilizzare un foglio di stile personalizzato 
     857 
     858Dato che l'HTML generato è contenuto strutturato, puoi fare ciò che ti piace con la presentazione. 
     859 
     860Puoi definire un CSS alternativo da usare con un modulo di amministrazione al posto di quello di default aggiungendo un parametro `css` alla configurazione del generatore, come mostrato nel Listato 14-38. 
     861 
     862Listato 14-38 - Usare uno stylesheet personalizzato invece di quello di default 
     863 
     864    generator: 
     865      class:              sfPropelAdminGenerator 
     866      param: 
     867        model_class:      Comment 
     868        theme:            default 
     869        css:              mystylesheet 
     870 
     871Alternativamente puoi usare i meccanismi forniti dal modulo `view.yml` per sovrascrivere gli stili per ogni vista. 
     872 
     873### Creare un header ed un footer personalizzati 
     874 
     875Le viste `list` ed `edit` includono sistematicamente partial per l'header ed il footer. Per default non c'è alcun partial nella cartella `templates/` di un modulo di amministrazione, ma per averlo incluso automaticamente ne devi semplicemente aggiungere uno con uno dei seguenti nomi: 
     876 
     877    _list_header.php 
     878    _list_footer.php 
     879    _edit_header.php 
     880    _edit_footer.php 
     881 
     882Ad esempio, se vuoi aggiungere un header personalizzato per la vista `article/edit`, crea un file chiamato `_edit_header.php` come nel Listato 14-39. Funzionerà senza ulteriori configurazioni. 
     883 
     884Listato 14-39 - Esempio di header partial `edit`, in `modules/articles/template/_edit_header.php` 
     885 
     886    <?php if ($article->getNbComments() > 0): ?> 
     887      <h2>This article has <?php echo $article->getNbComments() ?> comments.</h2> 
     888    <?php endif; ?> 
     889 
     890Nota che un partial `edit` ha sempre accesso all'oggetto corrente tramite una variabile con lo stesso nome del modulo, e che un partial `list` ha sempre accesso al pager corrente tramite la variabile `$pager`. 
     891 
     892>**SIDEBAR** 
     893>Chiamare le azioni dell'amministrazione tramite parametri personalizzati 
     894> 
     895>Le azioni del modulo di amministrazione possono ricevere parametri personalizzati utilizzando l'argomento `query_string` nell'helper `link_to()`. Ad esempio, per esterndere il partial precedente `_edit_header` con un link ai commenti di un articolo, scrivi: 
     896> 
     897> 
     898>      <?php if ($article->getNbComments() > 0): ?> 
     899>      <a name="This article has <?php echo link_to($article->getNbComments().' comments', 'comment/list', array('query_string' => 'filter=filter&filters%5Barticle_id%5D='.$article->getId())) ?>"></a><h2>This article has <?php echo link_to($article->getNbComments().' comments', 'comment/list', array('query_string' => 'filter=filter&filters%5Barticle_id%5D='.$article->getId())) ?></h2> 
     900>      <?php endif; ?> 
     901> 
     902>Per una versione più leggibile: 
     903> 
     904>      'filter=filter&filters[article_id]='.$article->getId() 
     905> 
     906>Esso filtra i commenti per visualizzare solo quelli relativi a `$article`. Usando l'argomento query_string, puoi specificare un ordinamento e/o un filtro per viste personalizzate. 
     907 
     908### Personalizzare il tema 
     909 
     910Ci sono altri partial ereditati dal framework che puoi sovrascrivere nella cartella `templates/` del modulo perché rispondano alle tue esigenze. 
     911 
     912I template del generatore sono divisi in piccole parti che possono essere sovrascritte indipendentemente, ed anche le azioni possono essere cambiate ad una ad una. 
     913 
     914Comunque, se volessi sovrascrivere diversi moduli nello stesso modo, dovresti probabilmente creare un tema. Si tratta di un set completo di template ed azioni che possono essere usate in un modulo di amministrazione se specificato nel valore `theme` all'inizio del file `generator.yml`. Con il tema di default, symfony usa i file definiti in `$sf_symfony_lib_dir/plugins/sfPropelPlugin/data/generator/sfPropelAdmin/default/`. 
     915 
     916I file del tema devono essere situati in una struttura ad albero del progetto, nella cartella `data/generator/sfPropelAdmin/[theme_name]/template/`, e potresti iniziare un nuovo tema copiando i file di quello di default (situati in `$sf_symfony_lib_dir/plugins/sfPropelPlugin/data/generator/sfPropelAdmin/default/template/`). In questo modo, sei sicuro che tutti i file necessari ad un tema saranno presenti: 
     917 
     918    // Partials, in [theme_name]/template/templates/ 
     919    _edit_actions.php 
     920    _edit_footer.php 
     921    _edit_form.php 
     922    _edit_header.php 
     923    _edit_messages.php 
     924    _filters.php 
     925    _list.php 
     926    _list_actions.php 
     927    _list_footer.php 
     928    _list_header.php 
     929    _list_messages.php 
     930    _list_td_actions.php 
     931    _list_td_stacked.php 
     932    _list_td_tabular.php 
     933    _list_th_stacked.php 
     934    _list_th_tabular.php 
     935     
     936    // Actions, in [theme_name]/template/actions/actions.class.php 
     937    processFilters()     // Process the request filters 
     938    addFiltersCriteria() // Adds a filter to the Criteria object 
     939    processSort() 
     940    addSortCriteria() 
     941 
     942Stai attento al fatto che i template in effetti sono template di template, ovvero file PHP di cui verrà fatto il parsing tramite una utility speciale per generare i template secondo le impostazioni del generatore (questa viene chiamata fase di compilazione). I template generate devono ancora contenere codice PHP da eseguire durante il browsing effettivo, per cui i template di template usano una sintassi alternativa per mantenere il codice PHP non eseguibile al primo passo. Il Listato 14-40 mostra un estratto di una template di template di default. 
     943 
     944Listato 14-40 - Sintassi di template di template 
     945 
     946    <?php foreach ($this->getPrimaryKey() as $pk): ?> 
     947    [?php echo object_input_hidden_tag($<?php echo $this->getSingularName() ?>,'get<?php echo $pk->getPhpName() ?>') ?] 
     948    <?php endforeach; ?> 
     949 
     950In questo listato, il codice PHP introdotto da <?  eseguito immediatamente (in compilazione), quello che comincia con [? viene solo eseguito in esecuzione, ma il template engine trasforma infine i tag in modo che il template finale risulta: 
     951 
     952    <?php echo object_input_hidden_tag($article, 'getId') ?> 
     953 
     954Gestire template di template è difficoltoso, per cui se vuoi creare il tuo tema il consiglio migliore è quello di partire da quello di default e modificarlo passo passo, e testarlo estensivamente. 
     955 
     956>**TIP** 
     957>Puoi anche pacchettizzare un tema in un plugin, che lo rende più riutilizzabile e facile da distribuire su più applicazioni. Consulta il Capitolo 17 per maggiori informazioni. 
     958 
     959>**SIDEBAR 
     960>Costruire il tuo generatore 
     961>I generatori di amministrazione usano entrambi un set di componenti interni di symfony che automatizzano la creazione di azioni e template generate nella cache, l'utilizzo dei temi, ed il parsing di template di template. 
     962> 
     963>Ciò significa che symfony fornisce tutti gli strumenti per costruire il tuo proprio generatore, che può essere come quello esistente o completamente differente. La generazione di un modulo è gestita dal metodo `generate()` della classe `sfGeneratorManager`. Ad esempio, per generare una amministrazione, symfony chiama internamente: 
     964> 
     965>     [php] 
     966>     $generator_manager = new sfGeneratorManager(); 
     967>     $data = $generator_manager->generate('sfPropelAdminGenerator', $parameters); 
     968> 
     969> Se vuoi costruire il tuo generatore, dovresti guardare le API per le classi `sfGeneratorManager` e `sfGenerator`, ed usare come esempi le classi `sfAdminGenerator` e `sfCRUDGenerator`. 
     970 
     971Sommario 
     972-------- 
     973 
     974Per generare automaticamente applicazioni di backend, la base sono uno schema ed un modello di oggetti ben definiti. Puoi modificare il codice PHP degli scaffolding, ma i moduli di amministrazione generati sono da modificare per lo più tramite configurazione. 
     975 
     976Il file `generator.yml` è il cuore della programmazione di backend generati. Permette una personalizzazione completa di contenuti, funzionalità e del look and feel delle viste `list` ed `edit`. Puoi gestire label, campi, suggerimenti, filtri, ordinamenti, dimensioni di pagine, tipi di input, relazioni, interazioni personalizzate e credenziali direttamente in YAML, senza una linea di codice PHP. 
     977 
     978Se il generatore non supporta nativamente la funzionalità di cui hai bisogno, i partial e la possibilità di sovrascrivere le azioni forniscono un'estensibilità completa. Inoltre, puoi riusare i tuoi adattamenti ai meccanismi del generatore grazie ai temi. 
     979 
     980}}}