Capitolo 14 - Admin Generator
Molte applicazioni sono basate su dati memorizzati in un database e offrono un'interfaccia per accedervi. Symfony automatizza il processo ripetitivo della creazione di un modulo che fornisca capacità di manipolazione dei dati basati su Propel o Doctrine. Se l'oggetto del modello è definito in modo appropriato, symfony può addirittura generare un intero sito di amministrazione automaticamente. Questo capitolo descrive l'utilizzo dell'admin generator, distribuito con i plugin di Propel e Doctrine. Esso si basa su uno speciale file di configurazione con una sintassi completa, quindi la maggior parte di questo capitolo ne descrive le varie possibilità.
Generazione del codice basato sul modello
In un'applicazione web, le operazioni di accesso ai dati possono essere categorizzate come segue:
- Creazione di una riga
- Recupero di una o più righe
- Aggiornamento di una riga (e modifica delle sue colonne)
- Eliminazione di una riga
Queste operazioni sono così comuni che hanno un acronimo: CRUD (dalle iniziali inglesi di Create, Replace, Update, Delete). Molte pagine possono essere ridotte a una di esse. Per esempio, in un'applicazione forum, la lista degli ultimi messaggi è un'operazione di recupero, mentre la risposta è un'operazione di creazione.
Le azioni e i template di base che implementano le operazioni CRUD per una data tabella sono create ripetutamente nelle applicazioni web. In symfony, il livello del modello contiene sufficienti informazioni per consentire la generazione del codice per le operazioni CRUD, in modo da accelerare la parte iniziale delle interfacce di backend.
Esempio di modello di dati
Lungo questo capitolo, i listati dimostreranno le capacità dell'admin generator di symfony
basandosi su un semplice esempio, che ricorderà il capitolo 8. Questo è il ben noto
esempio dell'applicazione blog, contenente le due classi BlogArticle e BlogComment.
Il listato 14-1 mostra lo schema, illustrato in Figura 14-1.
Listato 14-1 - Schema Propel dell'esempio di applicazione blog
---
propel:
blog_category:
id:
name: varchar(255)
blog_author:
id:
name: varchar(255)
blog_article:
id:
title: varchar(255)
content: longvarchar
blog_author_id:
blog_category_id:
is_published: boolean
created_at:
blog_comment:
id:
blog_article_id:
author: varchar(255)
content: longvarchar
created_at:
Figura 14-1 - Esempio di modello dei dati

Non c'è una regola particolare da seguire durante lo schema, per consentire la generazione del codice. Symfony userà lo schema così com'è e interpreterà i suoi attributi per generare l'amministrazione.
Per ottenere il massimo da questo capitolo, occorre implementare effettivamente gli esempi. Si otterrà una migliore comprensione di cosa symfony genera e di cosa può essere realizzato col codice generate, se si ha una visione di ogni passo descritto nei listati. L'inizializzazione del modello è semplice: basta richiamare il task
propel:build(odoctrine:build):$ php symfony propel:build --all --no-confirmation
Poiché l'interfaccia di amministrazione si basa su alcuni metodi magici per facilitare
i compiti, occorre creare un metodo __toString() in ogni classe del modello.
class BlogAuthor extends BaseBlogAuthor { public function __toString() { return $this->getName(); } } class BlogCategory extends BaseBlogCategory { public function __toString() { return $this->getName(); } } class BlogArticle extends BaseBlogArticle { public function __toString() { return $this->getTitle(); } }
Si può fare in modo che Propel aggiunga automaticamente il metodo magico
__toString(). Basta aggiungere la proprietàprimaryString: truealla colonna desiderata. Doctrine invece lo aggiunge automaticamente alla prima colonna di testo disponibile.
Amministrazione
Symfony può generare moduli del backend, basati sulle definizioni delle classi del modello trovate nel
file schema.yml. Si può creare un intero sito di amministrazione, composto interamente
da moduli di amministrazione generati. Gli esempi di questa sezione descriveranno i moduli
di amministrazione aggiunti a un'applicazione chiamata backend. Se il progetto non ha
ancora un'applicazione con questo nome, occorre crearla richiamando il seguente task:
$ php symfony generate:app backend
I moduli di amministrazione interpretano il modello tramite uno speciale file di
configurazione chiamato generator.yml, che può essere modificato per estendere tutte le
componenti generate e l'apparenza del modulo stesso. Tali moduli beneficiano del consueto
meccanismo descritto nei capitoli precedenti (layout, rotte, configurazione
personalizzata, caricamento automatico, eccetera). Si possono anche sovrascrivere azioni e
template generati, per poter integrare le caratteristiche desiderate nell'amministrazione
generate, ma generator.yml dovrebbe soddisfare la maggior parte delle esigenze comuni e
restringere l'uso del codice PHP a quelle veramente specifiche.
Anche se la maggior parte delle esigenze è coperta dal file di configurazione
generator.yml, si può anche configurare un modulo di amministrazione tramite una classe di configurazione, come vedremo più avanti in questo capitolo.
Inizializzare un modulo di amministrazione
Con symonfy, si può costruire un'amministrazione basandosi sui modelli. Un modulo viene generato in base a un oggetto Propel o Doctrine, usando uno dei seguenti task:
// Propel
$ php symfony propel:generate-admin backend BlogArticle --module=article
// Doctrine
$ php symfony doctrine:generate-admin backend BlogArticle --module=article
I moduli di amministrazione sono basati su un'architettura REST. Il task
propel:generate-adminaggiunge automaticamente al file di configuraizonerouting.ymluna rotta di questo tipo:--- # apps/backend/config/routing.yml article: class: sfPropelRouteCollection options: model: BlogArticle module: article with_wildcard_routes: trueSi può anche creare una propria rotta e passare il nome come parametro del task, al posto del nome della classe del modello:
$ php symfony propel:generate-admin backend article --module=article
Questa chiamata genera un modulo article nell'applicazione backend, basato sulla
definizione della classe BlogArticle, accessibile da:
http://localhost/backend_dev.php/article
L'aspetto del modulo generato, illustrato nelle figure 14-2 e 14-3, è abbastanza sofisticato da renderlo subito usabile per un'applicazione commerciale.
Se non si vede questo aspetto (mancano stili e immagini), occorre installare i file necessari nel progetto, eseguendo il task
plugin:publish-assetstask:$ php symfony plugin:publish-assets
Figura 14-2 - Vista list del modulo article nell'applicazione backend

Figura 14-3 - Vista edit del modulo article nell'applicazione backend

Uno sguardo al codice generato
Il codice del modulo amministrativo article, nella cartella
apps/backend/modules/article/, sembra vuoto perché è stato solo inizializzato. Il modo
migliore per controllare il codice generato è quello di interagire tramite il browser,
quindi andare a guardare nella cartella cache/. Il listato 14-2 elenca le azioni e i
template generati nella cache.
Listato 14-2 - Elementi amministrativi generati, in cache/backend/ENV/modules/autoArticle/
// Azioni in actions/actions.class.php
index // Mostra l'elenco delle righe della tabelle
filter // Aggiorna i filtri usati dalla lista
new // Mostra il form per inserire una nuova riga
create // Crea una nuova riga
edit // Mostra un form per modificare una riga
update // Aggiorna una riga esistente
delete // Elimina una riga
batch // Esegue un'azione su una lista di righe scelte
batchDelete // Esegue un'eliminazione su una lista di righe scelte
// In templates/
_assets.php
_filters.php
_filters_field.php
_flashes.php
_form.php
_form_actions.php
_form_field.php
_form_fieldset.php
_form_footer.php
_form_header.php
_list.php
_list_actions.php
_list_batch_actions.php
_list_field_boolean.php
_list_footer.php
_list_header.php
_list_td_actions.php
_list_td_batch_actions.php
_list_td_stacked.php
_list_td_tabular.php
_list_th_stacked.php
_list_th_tabular.php
_pagination.php
editSuccess.php
indexSuccess.php
newSuccess.php
Questo mostra che un modulo amministrativo generato è composto principalmente da tre viste,
list, new e edit. Se si guarda nel codice, lo si troverà molto modulare, leggibile
ed estensibile.
Introduzione al file di configurazione generator.yml
I moduli amministrativi generati si basano su paremetri trovati nel file di configurazione
generator.yml. Per vedere la configurazione predefinita di un nuovo modulo
amministrativo, aprire il file generator.yml, che si trova nella cartella
backend/modules/article/config/generator.yml, riprodotto nel listato 14-3.
Listato 14-3 - Configurazione predefinta del generatore, in backend/modules/article/config/generator.yml
---
generator:
class: sfPropelGenerator
param:
model_class: BlogArticle
theme: admin
non_verbose_templates: true
with_show: false
singular: BlogArticle
plural: BlogArticles
route_prefix: blog_article
with_propel_route: 1
actions_base_class: sfActions
config:
actions:
fields:
list:
filter:
form:
edit:
new:
Questa configurazione è sufficiente per generare l'amministrazione di base. Ogni
personalizzazione va aggiunta sotto la chiave config. Il listato 14-4 mostra un tipico
file generator.yml personalizzato.
Listato 14-4 - Configurazione tipica completa del generatore
gIn questa configurazione ci sono sei sezioni. Quattro di esse rappresentano le viste
(list, filter, new e edit) e due di esse sono "virtuali" (fields e form)
ed esistono solo per scopi di configurazione.
Le sezioni seguenti spiegano in dettaglio tutti i parametri che possono essere usati nel file di configurazione.
Configurazione del generatore
Il file di configurazione del generatore è molto potente e consente di alterare la generazione in molti modi. Ma queste capacità hanno un prezzo: la descrizione globale della sintassi è lunga da leggere e da imparare, rendendo questo capitolo il più lungo di questo libro.
Gli esempi di questa sezione modificheranno il modulo article e il modulo comment,
basato sulla definizione della classe BlogComment. Per creare ques'ultimo, basta
lanciare il comando:
$ php symfony propel:generate-admin backend BlogComment --module=comment
Figura 14-4 - Cheat sheet dell'administration generator

Campi
Le colonne predefinite della vista list sono quelle definite in schema.yml. I campi
delle viste new e edit sono quelli definiti nel form associato al modello
(BlogArticleForm). Nel file generator.yml si può scegliere quali campi mostrare,
quali nascondere e aggiungere campi nuovi, anche se non hanno una corrispondenza diretta
con l'oggetto del modello.
Impostazioni dei campi
Il generatore dell'amministrazione crea un campo per ogni colonna nel file schema.yml.
Sotto la chiave fields si può modificare il modo in cui i campi sono mostrati,
formattati, ecc. Per esempio, le impostazioni dei campi mostrate nel listato 14-5
definiscono una classe personalizzata per la label del campo title e una label e un
testo di aiuto per il campo content. Le sezioni seguenti descrivono nel dettaglio il
funzionamento di ogni parametro.
Listato 14-5 - Impostare una label personalizzata per un evento
cOltre alla definizione per tutte le viste, si possono configurare le impostazioni solo
per una vista specifica (list, filter, form, new o edit), come mostrato nel
listato 14-6.
Listato 14-6 - Impostazioni globali vista per vista
cC'è un principio generale: ogni impostazione inserita sotto la chiave fields può
essere sovrascritta nelle aree specifiche delle viste. Le regole di sovrascrittura sono
le seguenti:
neweeditereditano daform, che eredita dafieldslisteredita dafieldsfiltereredita dafields
Aggiungere dei campi
I campi definiti nella sezione fields possono essere mostrati, nascosti, ordinati e
raggruppati in vari modi per ogni vista. La chiave display è usata per questo scopo.
Per esempio, per riordinare i campi del modulo comment, usare il codice del listato 14-7.
Listato 14-7 - Scegliere i campi da mostrare, in modules/comment/config/generator.yml
La vista list mostrerà tre colonne, come mostrato in figura 14-5, mentre le viste new
e edit mostreranno quattro campi, divisi in due gruppi, come in figura 14-6.
Figura 14-5 - Impostazioni personalizzate delle colonne nella vista list

Figura 14-6 - Campi raggruppati nella vista edit

Dunque si possono usare le impostazioni display in due modi:
- Per la vista
list: inserire i campi in un array per scegliere le colonne da mostrare e l'ordine in cui appaiono. - Per le viste
form,neweedit: usare un array associativo per raggruppare i campi col nome del gruppo come chiave, oppureNONEper un gruppo senza nome. I valori sono ancora un array di colonne ordinate. Si faccia attenzione a elencare tutti i campi obbligatori del form o si potrebbero avere problemi con la validazione (vedere capitolo 10).
Campi personalizzati
Di fatto, i campi configurati in generator.yml non necessitano di colonne reali
corrispondenti nello schema. Se la classe relativa offre un getter, può essere usato come
un campo per la vista list. Se non ci sono getter o setter, si può comunque usare nella
vista edit. Per esempio, si può estendere il modello BlogArticle con un metodo
getNbComments() simile a quello nel listato 14-8.
Listato 14-8 - Aggiungere un getter personalizzato nel modello, in lib/model/BlogArticle.php
public function getNbComments() { return $this->countBlogComments(); }
In questo modo nb_comments è disponibile come campo nel modulo generato (si noti che
il getter usa una versione camelCase del nome del campo), come nel listato 14-9.
Listato 14-9 - I getter personalizzati forniscono colonne aggiuntive, in backend/modules/article/config/generator.yml
---
config:
list:
display: [title, blog_author, blog_category, nb_comments]
La vista list dell'articolo article è mostrata in figura 14-07.
Figura 14-07 - Campo personalizzato nella vista list

Campi con partial
Il codice che si trova nel modello deve essere indipendente dalla presentazione. L'esempio
del metodo getArticleLink() visto prima non rispecchia questo principio di separazione
tra i livelli, perché del codice della vista sta nel livello del modello. Di fatto, se si
prova a usare questa configurazione, ci si troverà con un collegamento mostrato come un
tag <a>, perché sottoposto a escape. Per raggiungere lo stesso scopo in modo corretto,
si dovrebbe inserire il codice che mostra HTML per un campo personalizzato in un partial.
Fortunatamente, il generatore di amministrazione consente di dichiarare un campo con un
trattino basso come prefisso. In questo caso, il file generator.yml del listato 14-11 va
modificato come nel listato 14-12.
Listato 14-12 - Partial usato come colonna aggiuntiva. Usare il prefisso _
---
config:
list:
display: [id, _article_link, created_at]
Per funzionare, un partial _article_link.php deve essere creato nella cartella
modules/comment/templates/, come nel listato 14-13.
Listato 14-13 - Esempio di partial per la vista list, in modules/comment/templates/_article_link.php
<?php echo link_to($BlogComment->getBlogArticle()->getTitle(), 'blog_article_edit', $BlogComment->getBlogArticle()) ?>
Si noti che il template del partial ha accesso all'oggetto corrente tramite una variabile
chiamata come la classe (in questo esempio, $BlogComment).
Figura 14-08 - Campo partial nella vista list

La separazione dei livelli è stata rispettata. Se ci si abitua a questa seprazione, ci si ritroverà con applicazioni più facili da mantenere.
Se occorre personalizzare le proprietà di un campo partial, si può fare come per un campo
normale, sotto la chiave fields. Basta non includere il prefisso (_) nella chiave.
Vedere come esempio il listato 14-14.
Listato 14-14 - Proprietà di un campo partial personalizzate sotto la chiave fields
Se un partial si affolla con troppa logica, probabilmente andrebbe sostituito con un
component. Basta cambiare il prefisso _ in ~, come si può vedere nel listato 14-15.
Listato 14-15 - I component possono essere usati come colonne aggiuntive. Usare il prefisso ~
---
config:
list:
display: [id, ~article_link, created_at]
Nel template generato, questo risulterà in una chiamata al componente articleLink del
modulo corrente.
I campi personalizzati e i campi partial possono essere usati nelle viste
list,new,editefilter. Se si usa lo stesso partial per viste diverse, il contesto (list,new,editofilter) viene memorizzato nella variabile$type.
Personalizzazione della vista
Per cambiare l'aspetto delle viste new, edit e list, si potrebbe essere tentati di
modificare i template. Ma siccome sono generati automaticamente, non è una buona idea.
Invece, si dovrebbe usare il file generator.yml, che può fare quasi tutto senza
sacrificare la modularità.
Cambiare il titolo di una vista
Oltre a un insieme personalizzato di campi, le pagine list, new e edit possono
avere un titolo personalizzato. Per esempio, se si vuole personalizzare il titolo delle
viste article, basta fare come nel listato 14-16. La vista edit risultante è
illustrata in figura 14-09.
Listato 14-16 - Impostare un titolo per ogni vista, in backend/modules/article/config/generator.yml
---
config:
list:
title: Lista di articoli
new:
title: Nuovo articolo
edit:
title: Modifica articolo %%title%% (%%id%%)
Figura 14-09 - Titolo personalizzato nella vista edit

Poiché i titoli predefiniti usano il nome della classe, spesso vanno bene, a patto di aver usato dei nomi di classi espliciti.
Nei valori stringa di
generator.yml, si può accedere al valore di un campo tramite il nome del campo stesso, preceduto e seguito da%%.
Aggiungere degli aiuti
Nelle viste list, new, edit e filter si possono aggiungere dei testi di aiuto, per
descrivere meglio i campi mostrati. Per esempio, per aggiungere un aiuto al campo
blog_article_id della vista edit del modulo comment, aggiungere una proprietà help
sotto la chiave fields, come nel listato 14-17. Il risultato è mostrato in figura 14-10.
Listato 14-17 - Impostare un testo di aiuto nella vista edit, in modules/comment/config/generator.yml
Figura 14-10 - Testo di aiuto nella vista edit

Nella vista list, i testi di aiuto sono mostrati nell'intestazione della colonna, mentre
nelle viste new, edit e filter sono mostrati sotto ciascun campo.
Modificare il formato delle date
Si possono mostrare le date con un formato personalizzato, usando l'opzione date_format,
come nel listato 14-18.
Listato 14-18 - Formattare una data nella vista list
Accetta gli stessi parametri dell'helper format_date(), descritto nel capitolo
precedente.
I template dell'amministrazione sono pronti per i18N
I moduli generati sono fatti di stringhe di interfaccia (nomi di azioni, paginazione, ecc.) e di stringhe personalizzate (titoli, label, messaggi di aiuto, ecc.).
Le traduzioni delle stringhe di interfaccia sono distribuite con symfony per moltissime lingue. Ma si possono anche aggiungere i propri o sovrascrivere quelli predefiniti, creando un file XLIFF per il catalogo
sf_adminnella cartellai18n(apps/backend/i18n/sf_admin.XX.xml, doveXXè il codice ISO della lingua).Tutte le stringhe personalizzate trovate nei template generati sono anche automaticamente internazionalizzate, (cioè incluse in una chiamata all'helper
__()). Questo vuol dire che si possono facilmente tradurre, aggiungendo le traduzioni delle frasi in un file XLIFF, nella cartellaapps/backend/i18n/, come spiegato nel capitolo precedente.Si può modificare il catalogo predefinito da usare per le stringhe personalizzate, specificando il parametro
i18n_catalogue:--- generator: class: sfPropelGenerator param: i18n_catalogue: admin
Personalizzazioni specifiche della vista list
La vista list può mostrare i dettagli di una riga in modo tabulare o impilato. Contiene
inoltre filtri, paginazione e opzioni di ordinamento. Queste caratteristiche possono
essere modificate dalla configurazione, come descritto nelle sezioni seguenti.
Cambiare il layout
I collegamenti predefiniti tra la vista list e la vista edit avviene nella colonna
della chiave primaria. Tornando alla figura 14-08, si vede che la colonna id nella lista
dei commenti non solo mostra la chiave primaria di ogni commento, ma anche un collegamento
che consente agli utenti di accedere alla vista edit.
Se si preferisce che il collegamento ai dettagli di una riga appaiono su una colonna
diversa, basta aggiungere un prefisso = al nome della colonna, sotto la chiave display.
Il listato 14-19 mostra come rimuovere id dai campi mostrati da list e come inserire
il collegamento nel campo content. Vedere la figura 14-11 per una schermata.
Listato 14-19 - Spostare il collegamento per la vista edit nella vista list, in modules/comment/config/generator.yml
---
config:
list:
display: [_article_link, =content]
Figura 14-11 - Spostare il collegamento per la vista edit su un'altra colonna

La vista list usa il layout predefinito tabular, in cui i campi appaiono come colonne,
come mostrato in precedenza. Si può usare anche il layout stacked, in cui i campi sono
concatenati in una singola stringa, che si espande per tutta la larghezza della tabella.
Se si sceglie il layout stacked, bisogna impostare nella chiave params lo schema che
definisce il valore di ciascuna linea della lista. Per esempio, il listato 14-20 definisce
un layout stacked per la vista list del modulo comment. Il risultato appare in
figura 14-12.
Listato 14-20 - Usare un layout stacked nella vista list, in modules/comment/config/generator.yml
---
config:
list:
layout: stacked
params: |
%%=content%%<br />:
(inviato da %%author%% in data %%created_at%% riguardo %%_article_link%%):
display: [created_at, author, content]
Figura 14-12 - Layout stacked nella vista list

Si noti che un layout tabular si aspetta un array di campi sotto la chiave display,
mentre un layout stacked usa la chiave params per la generazione del codice HTML di
ciascuna riga. Tuttavia, l'array display è usato ugualmente nel layout stacked, per
determinare quali intestazioni delle colonne sono disponibili, ai fini dell'ordinamento.
Filtrare i risultati
In una vista list si possono aggiungere un insieme di filtri interattivi. Con questi
filtri gli utenti possono visualizzare meno risultati e trovare più velocemente quelli
che cercano. Si possono configurare i filtri sotto la chiave filter, con un array di
nomi di campi. Per esempio, aggiungere un filtro sui campi blog_article_id, author e
created_at della vista list del modulo comment, come nel listato 14-21, per mostrare
un riquadro di filtri simile a quello in figura 14-13.
Listato 14-21 - Impostare i filtri nella vista list, in modules/comment/config/generator.yml
---
config:
list:
layout: stacked
params: |
%%=content%% <br />:
(inviato da %%author%% in data %%created_at%% riguardo %%_article_link%%):
display: [created_at, author, content]
filter:
display: [blog_article_id, author, created_at]
Figura 14-13 - Filtri nella vista list

I filtri mostrati da symfony dipendono dal tipo di colonna definito nello schema e possono essere personalizzati nella classe del form del filtro:
- Per le colonne di testo (come il campo
authornel modulocomment), il filtro è un input text, che consente ricerche basate su testi (aggiungendo automaticamente i caratteri jolly). - Per le chiavi esterne (come il campo
blog_article_idnel modulocomment), il filtro è un elenco a tendina delle righe della tabella correlata. Le opzioni sono quelle restituite dal metodo__toString()della classe correlata. - Per le colonne data (come il campo
created_atnel modulocomment), il filtro è una coppia di date, che consentono di scegliere un intervallo di tempo. - Per le colonne booleane, il filtro è un elenco a tendina con i valori
true,falseetrue or false, con l'ultimo come predefinito.
Come le viste new e edit sono legate a classi di form, i filtri usano le classi di
form di filtri associate col modello (per esempio BlogArticleFormFilterper il modello
BlogArticle). Si possono personalizzare i campi dei filtri definendo una classe per il
form dei filtri, sfruttando la potenza del framework dei form e usando tutti i widget dei
filtri disponibili. È molto facile, basta definire una classe class sotto la chiave
filter, come mostrato nel listato 14-22.
Listato 14-22 - Personalizzare la classe del form per i filtri
---
config:
filter:
class: BackendArticleFormFilter
Per disabilitare completamente i filtri, si può specificare
falsecome valore diclass.
Si possono anche usare dei partial per implementare una logica personalizzata nei filtri.
Ogni partial riceve il form form e gli attributi HTML attributes, da usare per la resa
dell'elemento del form. Il listato 14-23 mostra un esempio di implementazione di un
partial.
Listato 14-23 - Uso di un partial nel filtro
// Definire il partial, in templates/_state.php <?php echo $form[$name]->render($attributes->getRawValue()) ?>
--
---
# Aggiungere il partial alla lista dei filtri, in config/generator.yml
config:
filter: [created_at, _state]
Ordinare la lista
In una vista list, le intestazioni della tabelle sono collegamenti che possono essere
usati per riordinare la lista, come mostrato in figura 14-18. Questa intestazioni sono
mostrate in entrambi i layout, tabular e stacked. Cliccando questi collegamenti, la
pagina viene ricaricata con un parametro sort, che riordina la lista di conseguenza.
Figura 14-14 - Le intestazioni della tabella della vista list sono controlli di ordinamento

Si può riutilizzare la sintassi per puntare a una lista direttamente ordinata per una colonna:
<?php echo link_to('Lista dei commenti per data', '@blog_comment?sort=created_at&sort_type=desc' ) ?>
Si può anche definire un ordinamento predefinito per la vista list direttamente nel
file generator.yml. La sintassi segue l'esempio nel listato 14-24.
Listato 14-24 - Impostare un ordinamento predefinito su un campo nella vista list
---
config:
list:
sort: created_at
# Sintassi alternativa per specificare un verso di ordinamento
sort: [created_at, desc]
Solo i campi corrispondenti a vere colonne possono essere ordinabili, non le colonne personalizzate o partial.
Personalizzare la paginazione
L'amministrazione generata gestisce efficacemente grandi tabelle, perché la vista list
usa la paginazione. Quando il numero di righe in una tabella supera il numero massimo di
righe per pagina, compaiono i controlli per la paginazione in fondo alla lista. Per
esempio, la figura 14-19 mostra la lista dei commenti con sei commenti di prova nella
tabella e un limite di cinque commenti a pagina. La paginazione assicura buone
prestazioni, perché solo le righe mostrate sono estratte effettivamente dal database, e
una buona usabilità, perché anche tabelle con milioni di righe sono gestibili.
Figura 14-15 - Controlli di paginazione per liste lunghe

Si può personalizzare il numero di righe mostrate in ogni pagina col parametro
max_per_page:
---
config:
list:
max_per_page: 5
Usare una join per accelerare le pagine
Il generatore di amministrazione usa un semplice doSelect per recuperare una lista di
righe. Ma se si usano oggetto correlati nella lista, il numero di query richieste per
mostrare la lista potrebbe aumentare rapidamente. Per esempio, se si vuole mostrare il
nome dell'articolo in una lista di commenti, è necessaria una query in più per ogni riga
della lista, per poter recuperare l'oggetto BlogArticle correlato. Ma si può forzare
il paginatore a usare un metodo doSelectJoinXXX() per ottimizzare il numero di query,
usando il parametro peer_method (table_method per Doctrine).
---
config:
list:
peer_method: doSelectJoinBlogArticle
Il capitolo 18 spiega il concetto di join più approfonditamente.
Personalizzazioni specifiche per le viste new e edit
In una vista new o edit, l'utente può modificare il valore di ogni colonna di un
record. Il form predefinito usato dall'admin generator è il form associato col modello:
BlogArticleForm per il modello BlogArticle. Si può personalizzare la classe da usare,
definendo una voce class sotto form, come mostrato nel listato 14-25.
Listato 14-25 - Personalizzare la classe del form per le viste new e edit
---
config:
form:
class: BackendBlogArticleForm
L'uso di una classe personalizzata consente la personalizzazione di tutti i widget e di tutti i validatori usati dall'admin generator. La classe predefinita del form può quindi essere usata e personalizzata specificatamente per l'applicazione di frontend.
Si possono anche personalizzare label, messaggi di aiuto e l'aspetto del form,
direttamente nel file di configurazione generator.yml, come mostrato nel listato 14-26.
Listato 14-26 - Personalizzare l'aspetto del form
cGestire i campi partial
I campi partial possono essere usati nelle viste new e edit, proprio come nelle viste
list.
Gestire le chiavi esterne
Se lo schema definisce relazioni tra tabelle, i moduli di amministrazione generati se ne possono avvantaggiare e offrire maggiori controlli automatici, semplificando quindi di molto la gestione delle relazioni.
Relazioni uno a molti
Le relazioni 1-n sono prese in considerazione dal generatore di amministrazione. Come
illustrato precedentemente in figura 14-1, la tabella blog_comment è legata alla tabella
blog_article tramite un campo blog_article_id. Se si inizializza il modulo della
classe BlogComment col generatore di amministrazione, la vista edit mostrerà
automaticamente blog_article_id come un elenco a tendina, con i valori degli ID delle
righe della tabella blog_article (si veda ancora la figura 14-9 per un'illustrazione).
Lo stesso accade nella lista dei commenti legati a un articolo, nel modulo article
(relazione n-1).
Relazioni molti a molti
Symfony gestisce automaticamente anche le relazioni n-n, come mostrato in figura 14-16.
Figura 14-16 - Relazioni molti a molti

Personalizzando il widget usato per rendere la relazione, si può anche modificare la resa del campo (illustrata in figura 14-17):
Figura 14-17 - Controlli disponibili per relazioni molti a molti

Aggiungere interazioni
I moduli di amministrazione consentono agli utenti di eseguire le normali operazioni CRUD,
ma si possono anche aggiungere le proprie interazioni o restringere le possibili
interazioni per una vista. Per esempio, la definizione di interazione mostrata nel
listato 14-27 dà accesso a tutte le azioni CRUD predefinite nel modulo article.
Listato 14-27 - Definire le interazioni per ogni vista, in backend/modules/article/config/generator.yml
---
config:
list:
title: Lista di articoli
object_actions:
_edit:
_delete:
batch_actions:
_delete:
actions:
_new:
edit:
title: Corpo dell'articolo %%title%%
actions:
_delete:
_list:
_save:
_save_and_add:
In una vista list, ci sono tre impostazioni di azioni: le azioni disponibili per ogni
oggetto (object_actions), le azioni disponibili per una selezione di oggetti
(batch_actions) e le azioni disponibili per l'intera pagina (actions). La lista delle
interazioni definite nel listato 14-27 è resa come in figura 14-18. Ogni linea mostra un
bottone per modificare la riga e uno per cancellarla, più una spunta per cancellare una
selezione di righe. In fondo alla lista, un bottone consente la creazione di una nuova
riga.
Figura 14-18 - Interazioni nella vista list

Nelle viste new e edit, essendoci una sola riga alla volta, c'è un solo insieme di
azioni da definire (sotto actions). Le interazioni edit definite nel listato 14-27
rendono come in figura 14-23. Le azioni save e save_and_add salvano la riga corrente,
con la differenza che save mostra ancora la vista edit dopo il salvataggio, mentre
save_and_add mostra una vista new per aggiungere un'altra riga. L'azione
save_and_add è una scorciatoia molto utile per aggiungere diverse righe in successione.
Come per la posizione dell'azione delete, è separata dagli altri bottoni in modo da
evitare che sia cliccata per sbaglio.
I nomi delle interazioni che iniziano con un trattino basso (_) dicono a symfony di
usare l'icona e l'azione corrispondenti a tali interazioni. Il generatore di
amministrazione accetta _edit, _delete, _new, _list, _save, _save_and_add e
_create.
Figura 14-19 - Interazioni nella vista edit

Ma si possono anche aggiungere interazioni personalizzate, nel qual caso occorre specificare un nome che non inizi con un trattino basso e un'azione del modulo corrente, come nel listato 14-28.
Listato 14-28 - Definire un'interazione personalizzata
lOgni articolo nella lista ora mostrerà un collegamento Aggiungi un commento, come
mostrato in figura 14-20. Cliccandoci, si attiverà l'azione addComment del modulo
corrente. La chiave primaria dell'oggetto è aggiunta automaticamente ai parametri
della richiesta.
Figura 14-20 - Interazioni personalizzate nella vista list

L'azione addComment può essere implementata come nel listato 14-29.
Listato 14-29 - Implementare l'azione di interazione personalizzata, in actions/actions.class.php
public function executeAddComment($request) { $comment = new BlogComment(); $comment->setArticleId($request->getParameter('id')); $comment->save(); $this->redirect('blog_comment_edit', $comment); }
Le azioni batch ricevono un array di chiavi primarie delle righe selezionate, nel
parametro della richiesta ids.
Un'ultima nota sulle azioni: se si vogliono rimuovere completamente le azioni per una categoria, usare una lista vuota, come nel listato 14-30.
Listato 14-30 - Rimuovere tutte le azioni nella vista list
---
config:
list:
title: Lista di articoli
actions: {}
Validazione di form
La validazione è presa in carico automaticamente dal form usato nelle viste new e edit.
Si può personalizzare modificando le corrispondenti classi dei form.
Limitare le azioni usando le credenziali
Per un dato modulo di amministrazione, i campi e le interazioni disponibili possono variare a seconda delle credenziali dell'utente autenticato (fare riferimento al capitolo 6 per una descrizione delle caratteristiche di sicurezza di symfony).
I campi nel generatore accettano un parametro credentials, per apparire solo agli utenti
con le credenziali giuste. Questo per la voce list. Inoltre, il generatore può
nascondere delle interazioni, a seconda delle credenziali. Il listato 14-31 dimostra
queste caratteristiche.
Listato 14-31 - Uso delle credenziali in generator.yml
Modificare la presentazione dei moduli generati
Si può modificare la presentazione dei moduli generati, in modo che rispondano a schemi grafici esistenti, non solo applicando un foglio di stile personalizzato, ma anche sovrascrivendo i template predefiniti.
Usare un foglio di stile personalizzato
Poiché il codice HTML generato è un contenuto strutturato, si può fare quasi tutto con la presentazione.
Si può definire un CSS alternativo da usare per un modulo di amministrazione, al posto di
quello predefinito, aggiungendo un parametro css alla configurazione del generatore,
come nel listato 14-32.
Listato 14-32 - Usare un foglio di stile personalizzato al posto di quello predefinito
---
generator:
class: sfPropelGenerator
param:
model_class: BlogArticle
theme: admin
non_verbose_templates: true
with_show: false
singular: BlogArticle
plural: BlogArticles
route_prefix: blog_article
with_propel_route: 1
actions_base_class: sfActions
css: mystylesheet
In alternativa, si può usare il meccanismo fornito da view.yml del modulo, per
sovrascrivere gli stili in base alle viste.
Creare header e footer personalizzati
Le viste list, new e edit includono automaticamente un partial per header e footer.
Questi partial non sono definiti nella cartella templates/ del modulo, ma basta
aggiungerne uno con uno dei nomi seguenti, per vederli automaticamente inclusi:
_list_header.php
_list_footer.php
_form_header.php
_form_footer.php
Per esempio, se si vuole aggiungere un header personalizzato nella vista article/edit,
basta creare un file chiamato _form_header.php, come nel listato 14-33. Non sono
necessarie ulteriori configurazioni.
Listato 14-33 - Esempio di partial header edit, in modules/article/templates/_form_header.php
<?php if ($blog_article->getNbComments() > 0): ?> <h2>Questo articolo ha <?php echo $blog_article->getNbComments() ?> commenti.</h2> <?php endif; ?>
Si noti che un partial in edit ha sempre accesso all'oggetto corrente, tramite una
variabile con lo stesso nome della classe, e che un partial in list ha sempre accesso
al paginatore corrente, tramite la variabile $pager.
Personalizzazione del tema
Ci sono altri partial ereditati dal framework che possono essere sovrascritti nella
cartella templates/ del modulo, per soddisfare delle esigenze personali.
I template del generatore sono spezzati in piccole parti, che possono essere sovrascritte indipendentemente, e le azioni possono essere cambiate una per una.
Tuttavia, se si vogliono sovrascrivere tanti moduli nello stesso modo, probabilmente
conviene creare un tema riusabile. Un tema è un sottoinsieme di template e di azioni che
possono essere usati in un modulo di amministrazione, se specificato nel valore di theme
all'inizio di generator.yml. Col tema predefinito, symfony usa i file definiti in
sfConfig::get('sf_symfony_lib_dir')/plugins/sfPropelPlugin/data/generator/sfPropelModule/admin/.
I file del tema devono trovarsi in una struttura alberata del progetto, in una cartella
dal nome data/generator/sfPropelModule/[nome_tema]/. Si può creare un nuovo tema
copiando i file da quello predefinito:
// Partial, in [nome_tema]/template/templates/
_assets.php
_filters.php
_filters_field.php
_flashes.php
_form.php
_form_actions.php
_form_field.php
_form_fieldset.php
_form_footer.php
_form_header.php
_list.php
_list_actions.php
_list_batch_actions.php
_list_field_boolean.php
_list_footer.php
_list_header.php
_list_td_actions.php
_list_td_batch_actions.php
_list_td_stacked.php
_list_td_tabular.php
_list_th_stacked.php
_list_th_tabular.php
_pagination.php
editSuccess.php
indexSuccess.php
newSuccess.php
// Azioni, in [nome_tema]/parts
actionsConfiguration.php
batchAction.php
configuration.php
createAction.php
deleteAction.php
editAction.php
fieldsConfiguration.php
filterAction.php
filtersAction.php
filtersConfiguration.php
indexAction.php
newAction.php
paginationAction.php
paginationConfiguration.php
processFormAction.php
sortingAction.php
sortingConfiguration.php
updateAction.php
Si faccia attenzione, perché i file dei template sono in realtà template di template, cioè sono dei file PHP che saranno analizzati da un programma speciale per generare dei template basati sulle impostazioni del generatore (questo processo è chiamato fase di compilazione). I template generati devono comunque contenere codice PHP da eseguire durante la navigazione, quindi i template di template usano una sintassi alternativa per mantenere il codice PHP ineseguito durante il primo passo. Il listato 14-34 mostra un estratto di un template di template predefinito.
Listato 14-34 - Sintassi dei template di template
<h1>[?php echo <?php echo $this->getI18NString('edit.title') ?> ?]</h1> [?php include_partial('<?php echo $this->getModuleName() ?>/flashes') ?]
In questo listato, il codice PHP introdotto da <? viene eseguito immediatamente (in fase
di compilazione), mentre quello introdotto da [? viene eseguito solo durante l'esecuzione
vera e propria, ma il motore di template trasforma i tag [? in tag <?, in modo che il
template risultante appaia come questo:
<h1><?php echo __('Lista di tutti gli articoli') ?></h1> <?php include_partial('article/flashes') ?>
Non è facile gestire i template di template, quindi il consiglio migliore per chi volesse
creare un tema è quello di partire dal tema admin, modificarlo a piccoli passi e
testarlo in modo intensivo.
Si può anche impacchettare un tema per il generatore in un plugin, il che lo rende ancora più riusabile e facile da rilasciare in applicazioni multiple. Si faccia riferimento al capitolo 17 per maggiori informazioni.
Costruire un generatore personalizzato
Il generatore di amministrazione usa un insieme di componenti interni di symfony, che automatizzano la creazione di azioni e template generati nella cache, l'uso di temi e l'analisi dei template di template.
Questo vuol dire che symfony fornisce tutti gli strumenti per costruire un generatore personalizzato, che può assomigliare a quelli esistenti o essere completamente diverso. La generazione di un modulo è gestita dal metodo
generate()della classesfGeneratorManager. Per esempio, per generare un'amministrazione, symfony richiama internamente:$manager = new sfGeneratorManager(); $data = $manager->generate('sfPropelGenerator', $parameters);Se si vuole costruire un generatore, si dovrebbe dare un'occhiata alla documentazione delle API delle classi
sfGeneratorManageresfGeneratore prendere come esempi le classisfModelGeneratoresfPropelGenerator.
Riepilogo
Per generare automaticamente le applicazioni di backend, le basi sono uno schema ben definito e il modello degli oggetti. La personalizzazione dei moduli di amministrazione generati andrebbe fatta tramite la configurazione.
Il file generator.yml è il cuore della programmazione dei backend generati. Esso consente
una personalizzazione completa di contenuti, caratteristiche e aspetto delle viste list,
new e edit. Si possono gestire label, testi di aiuto, filtri, ordinamento, dimensione
della pagine, tipi di input, relazioni esterne, interazioni personalizzate e credenziali
direttamente in YAML, senza una singola riga di codice PHP.
Se il generatore di amministrazione non supporta nativamente una caratteristica richiesta, i campi partial e la possibilità di sovrascrivere le azioni forniscono una completa estensibilità. Inoltre, si possono riusare le personalizzazioni fatte sul generatore, grazie al meccanismo dei temi.
インデックス
Document Index
関連ページリスト
Related Pages
Capitolo 1 - introduzione a symfony
Capitolo 2 - Esplorazione del codice di symfony
Capitolo 3 - Utilizzare Symfony
Capitolo 4 - Le basi per la creazione delle pagine
Capitolo 5 - Configurare symfony
Capitolo 6 - All'interno del livello del controllore
Capitolo 7 - All'interno del livello della vista
Capitolo 8 - All'interno del livello del modello (Doctrine)
Capitolo 9 - Link e il sistema di routing
Capitolo 10 - I form
Capitolo 11 - Email
Capitolo 12 - Cache
Capitolo 13 - I18n e l10n
Capitolo 14 - Admin Generator
Capitolo 15 - Test funzionali e unitari
Capitolo 16 - Strumenti per la gestione dell'applicazione
Capitolo 17 - Estendere symfony
Capitolo 18 - Prestazioni
Capitolo 19 - Padroneggiare i file di configurazione di symfony
Appendice A - All'interno del livello del modello (Propel)
Appendice B - Licenza per la Documentazione Libera GNU
日本語ドキュメント
Japanese Documents
2011/01/18 Chapter 17 - Extending Symfony
2011/01/18 The generator.yml Configuration File
2011/01/18 Les tâches
2011/01/18 Emails
2010/11/26 blogチュートリアル(8) ビューの作成
リリース情報
Release Information
- 2.0 : 2.0.10(2011/02/06)
Symfony2日本語ドキュメント - 1.4 : 1.4.16(2011/12/13)
Changelog
