Development

Documentation/it_IT/book/1.1/04-The-Basics-of-Page-Creation

You must first sign up to be able to contribute.

Version 5 (modified by garak, 9 years ago)
corretta path immagine

Capitolo 4 - Le basi per la creazione di pagine

Curiosamente, il primo tutorial che i programmatori seguono per imparare un nuovo linguaggio o framework, è quello che visualizza sullo schermo "Ciao, mondo". E' strano pensare ad un computer come a qualcosa che possa salutare il mondo intero, in quanto ogni tentativo nel campo dell'intelligenza artificiale è finora sfociato solo in povere capacità di conversazione. Ma symfony non è più stupido di qualsiasi altro programma, e ne è la prova il fatto che puoi creare una pagina con scritto "Ciao, <il tuo nome>".

Questo capitolo ti insegnerà a creare un modulo, che è l'elemento strutturale che raggruppa le pagine. Imparerai anche come creare una pagina, che grazie al pattern MVC è diviso in azione e template. I link e le form sono le interazioni base del web; vedrai come inserirle in una template e gestirle in un'azione.

Creare lo scheletro di un modulo

Come spiegato nel Capitolo 2, symfony divide le pagine in moduli. Prima di creare una pagina, occorre creare un modulo, che inizialmente è una shell vuota con una struttura di file riconoscibile da symfony.

La linea di comando di symfony automatizza la creazione di moduli. Hai solo bisogno di chiamare il comando generate:module con il nome dell'applicazione ed il nome del modulo come argomenti. Nel capitolo precedente, hai creato l'applicazione frontend. Per poter aggiungere il modulo contenuto, scrivi i seguenti comandi:

> cd ~/myproject
> symfony generate:module frontend contenuto

>> dir+      ~/myproject/apps/frontend/modules/contenuto/actions
>> file+     ~/myproject/apps/frontend/modules/contenuto/actions/actions.class.php
>> dir+      ~/myproject/apps/frontend/modules/contenuto/templates
>> file+     ~/myproject/apps/frontend/modules/contenuto/templates/indexSuccess.php
>> file+     ~/myproject/test/functional/frontend/contenutoActionsTest.php
>> tokens    ~/myproject/test/functional/frontend/contenutoActionsTest.php
>> tokens    ~/myproject/apps/frontend/modules/contenuto/actions/actions.class.php
>> tokens    ~/myproject/apps/frontend/modules/contenuto/templates/indexSuccess.php

A parte le cartelle actions/ e templates/, questo comando crea solo tre file. Quello nella cartella test/ riguarda i test, e non hai bisogno di preoccupartene fino al Capitolo 15. Il file actions.class.php (mostrato nel Listato 4-1) redirige al modulo di congratulazioni di default. Il file templates/indexSuccess.php è vuoto.

Listato 4-1 - Azione di default generata automaticamente, in actions/actions.class.php

[php]
<?php

class contenutoActions extends sfActions
{
  public function executeIndex()
  {
    $this->forward('default', 'module');
  }
}

NOTE Se dai un'occhiata ad un effettivo actions.class.php, troverai molte più di queste poche linee, inclusi molti commenti. Questo perchè symfony raccomanda di utilizzare commenti PHP per la documentazione del tuo progetto, e di preparare ogni classe per essere compatibile con phpDocumentor (http://www.phpdoc.org/).

Per ogni modulo, symfony crea un'azione index di default. Essa è composta da un metodo chiamato executeIndex e da una template chiamata indexSuccess.php. Il significato del prefisso execute e del suffisso Success verrà spiegato rispettivamente nei Capitoli 6 e 7. Per il momento puoi considerare come una convenzione questo modo di chiamare metodi e file. Puoi vedere la pagina corrispondente (mostrata in Figura 4-1) navigando al seguente indirizzo:

http://localhost/frontend_dev.php/contenuto/index

L'azione di default index non sarà utilizzata in questo capitolo, per cui puoi rimuovere il metodo executeIndex() dalla classe actions.class.php, e cancellare il file indexSuccess.php dalla cartella templates/.

NOTE Symfony offre altri metodi oltre alla linea di comando per inizializzare un modulo. Uno di questi è creare a mano file e cartelle. In molti casi, le azioni ed i template di un modulo servono a gestire i dati di una data tabella. Dato che il codice per creare, selezionare, aggiornare e cancellare record da una tabella spesso è lo stesso, symfony fornisce un meccanismo per generare questo codice automaticamente. Controlla il Capitolo 14 per maggiori informazioni su questa tecnica.

Figura 4-1 - Pagina di default generata automaticamente

Pagina di default generata automaticamente

Aggiungere una pagina

In symfony, la logica di una pagina è memorizzata nelle azioni, mentre la presentazione in template. Le pagine senza una logica avranno bisogno comunque di un'azione vuota.

Aggiungere un'azione

La pagina "Ciao, mondo!" sarà accessibile tramite l'azione show. Per crearla, inserisci semplicemente un metodo chiamato executeShow alla classe contenutoActions, come mostrato nel Listato 4-2.

Listato 4-2 - Aggiungere un'azione significa aggiungere un metodo execute alla classe

[php]
<?php

class contenutoActions extends sfActions
{
  public function executeShow()
  {
  }
}

Il nome del metodo da aggiungere è sempre `executeXxx()`, dove Xxx è il nome dell'azione con la prima lettera maiuscola.

Ora, se navighi all'indirizzo:

http://localhost/frontend_dev.php/contenuto/show

symfony si arrabbierà dicendoti che manca il template showSuccess.php. Questo è normale; in symfony una pagina è sempre composta da un'azione e da un template.

CAUTION Le URL (non i nomi a dominio) sono case-sensitive, è così è symfony (anche se i nomi dei metodi non lo sono, in PHP). Questo significa che richiamando l'azione sHow con il browser, symfony restituirà un errore 404.

SIDEBAR Le URL sono parte della risposta

Symfony possiede un sistema di routing che ti permette di avere una separazione completa fra il nome effettivo dell'azione e l'URL necessaria a chiamarlo. Questo permette la personalizzazione delle URL come se fossero parte della risposta. Non sei più limitato né dalla struttura di file né dai parametri di richiesta; le URL per una azione possono essere la frase che preferisci. Ad esempio, la chiamata all'azione index di un modulo normalmente è tipo:

http://localhost/frontend_dev.php/article/index?id=123

Questa URL recupera un articolo da un database. In questo esempio, recupera un articolo (con id=123) nella sezione Europa e che parla di finanza in Francia. Ma l'URL può essere riscritta in modo completamente differente modificando il file di configurazione routing.yml:

http://localhost/articles/europe/france/finance.html

Non solo la URL che ne risulta è motore di ricerca-friendly, ma ha anche un significato per l'utente, il quale può utilizzare la barra degli indirizzi come una pseudo linea di comando per eseguire delle ricerche personalizzate, come la seguente:

http://localhost/articles/tagged/finance+france+euro

Symfony sa come fare il parsing e generare URL intelligenti per l'utente. Il sistema di routing estrae automaticamente i parametri dalla URL intelligente e li rende disponibili all'azione. Esso si occupa anche di formattare gli hyperlink inclusi nella risposta, in modo da farli sembrare "intelligenti". Il Capitolo 9 illustra questa funzione.

In generale, questo significa che il modo in cui si chiamano le azioni della tua applicazione non dovrebbe essere influenzato dal modo in cui dovrebbero apparire le URL che le chiamano, ma piuttosto secondo le loro funzioni nel contesto dell'applicazione. Il nome di un'azione spiega quello che l'azione fa effettivamente, e spesso è un verbo nella forma infinita (come show, list, edit, e così via). I nomi delle azioni possono essere totalmente invisibili all'utente, per cui non esitare ad usare nomi espliciti (come listByName o showWithComments). Risparmierai sui commenti del codice per spiegare ciò che fa la funzione, inoltre il codice sarà molto più leggibile.

Aggiungere un template

L'azione si aspetta un template che la renderizzi. Un template è un file all'interno della cartella templates/ di un modulo, chiamato come l'azione e come il suo termine. Il termine di default per un'azione è un "successo", per cui il template da creare per l'azione show si deve chiamare showSuccess.php.

In teoria dentro un template ci dovrebbe essere solo codice di presentazione, per cui cerca di minimizzare il codice PHP al suo interno. In effetti, una pagina che visualizzi semplicemente "Ciao, mondo!" può avere una template come quella del Listato 4-3.

Listato 4-3 - Il template contenuto/templates/showSuccess.php

[php]
<p>Ciao, mondo!</p>

Se tu avessi bisogno di utilizzare codice PHP nel template, dovresti evitare di usare la solita sintassi, come nel Listato 4-4. Invece, scrivi il tuo template utilizzando una sintassi alternativa, come mostrato nel Listato 4-5, per mantenere il codice comprensibile per non-programmatori. Non solo il codice finale sarà indentato correttamente, ma ti aiuterà anche a mantenere del codice PHP complesso nell'azione, perché solo le istruzioni di controllo (if, foreach, while, e così via) possiedono una sintassi alternativa.

Listato 4-4 - Sintassi PHP standard, corretta per le azioni ma non per i template

[php]
<p>Ciao, mondo!</p>
<?php

if ($test)
{
  echo "<p>".time()."</p>";
}

?>

Listato 4-5 - Sintassi PHP alternativa, corretta per i template

[php]
<p>Ciao, mondo!</p>
<?php if ($test): ?>
<p><?php echo time(); ?></p>
<?php endif; ?>

TIP Una buona regola per verificare che il template sia abbastanza leggibile, è controllare che non siano presenti parentesi graffe e che non ci sia codice HTML come output di PHP. E, la maggior parte delle volte, quando aprirai del codice PHP con <?php lo chiuderai sulla stessa linea con ?>.

Passare informazioni dall'azione al template

Il lavoro di un'azione è quello di eseguire tutti i calcoli complicati, recuperare dati e test, e settare variabili per poter essere testate o visualizzate da un template. Symfony rende possibile accedere direttamente agli attributi di una classe ($this->nomeVariabile) da un template nel namespace globale (tramite $nomeVariabile). I Listati 4-6 e 4-7 mostrano come passare informazioni da un'azione ad un template.

Listato 4-6 - Settare un attributo di un'azione per renderla disponibile ad un template

[php]
<?php

class frontendActions extends sfActions
{
  public function executeShow()
  {
    $today = getdate();
    $this->hour = $today['hours'];
  }
}

Listato 4-7 - Il template ha accesso diretto all'attributo

[php]
<p>Ciao, mondo!</p>
<?php if ($hour >= 18): ?>
<p>O forse dovrei dire buonasera? Sono già le <?php echo $hour ?>.</p>
<?php endif; ?>

Nota che l'utilizzo di tag di apertura corti (<?=, equivalente a <?php echo) non è raccomandato in applicazioni web professionali, dato che il tuo web server potrebbe essere configurato per comprendere più linguaggi di scripting, e di conseguenza confondersi. Inoltre, i tag di apertura corti non sono abilitati nella configurazione di default di PHP, che quindi andrebbe modificata. Infine, quando si ha a che fare con la validazione e con XML, si generano errori in quanto <? ha un significato speciale in XML.

NOTE Ogni template ha già accesso ad una piccola parte di dati senza settare alcuna variabile nell'azione. Ogni template può infatti chiamare i metodi degli oggetti $sf_request, $sf_params, $sf_response, e $sf_user. Essi contengono dati relativamente alla richiesta corrente, ai parametri di richiesta, alla risposta e alle sessioni. Presto imparerai ad usarli efficientemente.

Collegamenti ad altre azioni

Già sappiamo che c'è un disaccoppiamento tra il nome di un'azione e la URL usata per richiamarla. Quindi, se crei un link all'azione update nel template come nel Listato 4-10, funzionerà solo col routing di default. Se più avanti decidi di cambiare l'aspetto delle URL, avrai bisogno di rivedere tutti i template e cambiare i link.

Listing 4-10 - Link, il modo classico

[php]
<a href="/frontend_dev.php/contenuto/update?name=anonymous">
  Non dico mai il mio nome
</a>

Per evitare questa scocciatura, dovresti usare sempre l'helper link_to() per creare collegamenti alle azioni della tua applicazione. E se vuoi generare solo la parte della URL, l'helper url_for() è quello che fa per te.

Un helper non e' altro che una funzione PHP definita da symfony da utilizzare all'interno di template; scrive in output codice HTML ed e' piu' veloce da utilizzare piuttosto che scrivere lo stesso codice a mano. Utilizzando gli helper,. Il Listato 4-11 mostra l'uso degli helper per i link.

Listato 4-11 - Gli helper link_to() e url_for()

[php]
<p>Ciao, mondo!</p>
<?php if ($hour >= 18): ?>
<p>O forse dovrei dire buonasera? Sono già le <?php echo $hour ?>.</p>
<?php endif; ?> 
<form method="post" action="<?php echo url_for('content/update') ?>">
  <label for="name">What is your name?</label>
  <input type="text" name="name" id="name" value="" />
  <input type="submit" value="Ok" />
  <?php echo link_to('Non dico mai il mio nome','content/update?name=anonymous') ?>
</form>

Il codice HTML risultante sarà lo stesso del Listato precedente, con la differenza che se cambi le regole di routing tutti i template continueranno a comportarsi correttamente, riformattando le URL di conseguenza.

La manipolazione delle form merita un capitolo a parte, dato che symfony fornisce molti strumenti per renderla ancora più semplice. Imparerai di più su questi helper nel capitolo 10.

L'helper link_to(), come molti altri, accetta un altro argomento per opzioni speciali e attributi aggiuntivi. Il Listato 4-12 mostra un esempio con un argomento opzionale ed il codice HTML che ne risulta. L'argomento aggiuntivo può essere sia un array associativo che una semplice stringa con coppie chiave=valore separate da uno spazio bianco.

Listato 4-12 - La maggior parte degli helper accetta un argomento opzionale

[php]
// Opzioni passate come array
<?php echo link_to('Non dico mai il mio nome', 'contenuto/update?name=anonymous',
  array(
    'class'    => 'special_link',
    'confirm'  => 'Sei sicuro?',
    'absolute' => true
)) ?>

// Opzioni passate come stringa
<?php echo link_to('Non dico mai il mio nome', 'contenuto/update?name=anonymous',
  'class=special_link confirm=Sei sicuro? absolute=true') ?>

// Entrambi mostrano la stessa cosa
 => <a class="special_link" onclick="return confirm('Sei sicuro?');"
    href="http://localhost/frontend_dev.php/contenuto/update/name/anonymous">
    Non dico mai il mio nomee</a>

Ogni volta che usi un helper che genera un tag HTML, puoi sempre inserire attributi aggiuntivi (come la classe nell'esempio precedente) nel parametro opzionale. Potresti anche scrivere tali attributi nel modo "sporco e veloce" di HTML 4.0 (senza le doppie virgolette), e symfony si occuperà comunque di generarli nel corretto formato XHTML. Questa è un'altra ragione per cui l'utilizzo degli helper è più veloce di scrivere codice a mano.

NOTE Dato che richiede parsing e trasformazioni aggiuntive, la sintassi con la stringa è leggermente più lenta di quella con l'array.

Sia che l'utente invii informazioni tramite una form (di solito richiesta in POST) che tramite URL (richiesta in GET), puoi ricevere i dati relativi nell'azione tramite il metodo getParameter() dell'oggetto sfRequest. Il Listato 4-13 mostra come, in update, puoi ricevere il valore del parametro name.

Il beneficio derivante dall'utilizzo degli helper nei template non è altro che pura velocità di coding, scrivere codice chiaro e conciso. L'unico prezzo da pagare è il tempo necessario ad imparare ad usarli, che si esaurirà quando avrai finito di leggere questo libro, ed il tempo di scriverli, per il quale dovresti già avere delle scorciatoie nel tuo editor di testo preferito. Quindi, potresti anche non usare gli helper di symfony nei template, e scrivere codice HTML come hai sempre fatto, con una grande perdita di tempo e molto meno divertimento.

Listato 4-13 - Ricevere i dati dai parametri di richiesta nell'azione

[php]
<?php

class contenutoActions extends sfActions
{
  // ...

  public function executeUpdate($request)
  {
    $this->name = $request->getParameter('name');
  }
}

Per convenienza, tutti i metodi executeXxx() prendono l'oggetto sfRequest corrente come primo argomento.

Se la gestione dei dati è semplice, non c'è neppure bisogno di utilizzare l'azione per ricevere i dati. Il template infatti ha accesso ad un oggetto chiamato $sf_params, che offre un metodo get() per ricevere i parametri della richiesta, esattamente come getParameter nell'azione.

Se executeUpdate() fosse vuota, il Listato 4-14 mostra come il template updateSuccess.php potrebbe ricevere lo stesso parametro.

Listato 4-14 - Ricevere i parametri direttamente nel template

[php]
<p>Ciao, <?php echo $sf_params->get('name') ?>!</p>

NOTE Perché non usare invece le variabili $_POST, $_GET, o $_REQUEST? Perché altrimenti le tue URL fossero formattate diversamente (come in http://localhost/articles/europe/france/finance.html, senza ? o =), le solite variabili PHP non funzionerebbero, e solo il sistema di routing sarebbe capace di ricevere i dati. E potresti voler aggiungere filtri in input, per evitare l'esecuzione di codice di injection maligno, cosa possibile esclusivamente utilizzando un sistema di gestione dei parametri pulito.

L'oggetto $sf_params è più potente di un semplice getter. Ad esempio, se volessi semplicemente testare l'esistenza di un parametro, potresti usare il metodo $sf_params->has() invece di testare l'effettivo valore con get(), come mostrato nel Listato 4-15.

Listato 4-15 - Testare l'esistenza di un parametro nel template

[php]
<?php if ($sf_params->has('name')): ?>
  <p>Ciao, <?php echo $sf_params->get('name') ?>!</p>
<?php else: ?>
  <p>Ciao, Pinco Pallino!</p>
<?php endif; ?>

Forse hai già capito che questo può essere scritto in una linea sola. Come la maggior parte dei getter di symfony, sia il metodo $request->getParameter() nell'azione che il metodo $sf_params->get() nel template (che per la cronaca, chiamano lo stesso metodo dello stesso oggetto) accettano un secondo parametro: un valore di default se il primo non fosse disponibile.

[php]
<p>Ciao, <?php echo $sf_params->get('name', 'Pinco Pallino') ?>!</p>

Riepilogo

In symfony, le pagine sono composte da azioni (un metodo dentro il file actions/actions.class.php con il prefisso execute) e template (un file nella cartella templates/, il cui nome generalmente finisce con Success.php). Esse sono raggruppate in moduli, conformemente alla loro funzione nell'applicazione. Scrivere template è facilitato dagli helper, che sono funzioni fornite da symfony che generano codice HTML. E devi pensare alla URL come facente parte della risposta, che può essere formattata secondo i propri bisogni, per cui dovresti trattenerti dall'utilizzare qualsiasi riferimento diretto alle URL sia nei nomi delle azioni che nella gestione dei parametri.

Una volta imparati questi princìpi di base, puoi già scrivere un'applicazione intera con symfony. Ma richiederebbe troppo tempo, perché quasi ogni operazione che devi svolgere durante lo sviluppo è facilitato in un modo o nell'altro da qualche caratteristica di symfony... motivo per il quale il libro non si ferma qui.