Development

Documentation/it_IT/book/1.0/16-Application-Management-Tools

You must first sign up to be able to contribute.

Version 5 (modified by gscaglia, 9 years ago)
--

Capitolo 16 - Strumenti di gestione delle applicazioni

Sia durante la fase di sviluppo che durante quella di distribuzione gli sviluppatori hanno bisogno di strumenti di diagnostica per verificare che l'applicazione funzioni come ci si aspetta. Tale informazioni sono generalmente aggregate tramite utility di log e di debug. A causa del ruolo centrale che il framework (come symfony) gioca nello sviluppo, è importante che tali strumenti siano strettamente integrati.

Durante la vita di un'applicazione sul server di produzione, l'amministratore opera ripetutamente una grande quantità di operazioni, dalla rotazione dei log agli upgrade. Un framework dovrebbe fornire anche strumenti per automatizzare il più possibile tali task.

Questo capitolo spiega come gli strumenti di gestione delle applicazioni di symfony aiutano a soddisfare tali bisogni.

Logging

L'unico modo per capire cosa è andato storto durante l'esecuzione di una richiesta è controllare le tracce dell'esecuzione del processo. Fortunatamente, come imparerai in questa sezione, sia PHP che symfony tendono ad immagazzinare una grande quantità di dati di questo tipo.

Log di PHP

PHP possiede un parametro chiamato error_reporting definito in php.ini, che specifica quali eventi PHP devono essere loggati. Symfony ti permette di fare l'override di tale valore, sia per applicazione che per ambiente, nel file settings.yml, come mostrato nel Listato 16-1.

Listato 16-1 - Impostare il livello di reporting degli errori, in myapp/config/settings.yml

[php]
prod:
 .settings:
    error_reporting:  257

dev:
  .settings:
    error_reporting:  4095

I numero sono un modo più corto per indicare i livelli di errore (consulta la documentazione di PHP per maggiori dettagli). Fondalmentalmente, 4095 uno shortcut per E_ALL | E_STRICT, mentre 257 sta per E_ERROR | E_USER_ERROR (valori di default per ogni nuovo ambiente).

Per evitare problemi di prestazioni nell'ambiente di produzione, il server logga solo gli errori PHP critici. Nell'ambiente di sviluppo, invece, tutti gli eventi vengono loggati, in modo che lo sviluppatore abbia tutte le informazioni necessarie per rintracciare errori.

Puoi trovare i file dei log di PHP a seconda di come hai configurato il tuo php.ini. Se non hai mai cambiato la configurazione di default, probabilmente PHP usa i log del web server (come quelli di Apache). In tal caso, troverai i file nella cartella di log del web server.

Log di symfony

In aggiunta ai log standard di PHP, symfony può tenere traccia di molti eventi personalizzati. Puoi trovare tutti i log di symfony nella cartella myproject/log/. C'è un file per applicazione e ambiente. Ad esempio, il file di log per l'ambiente di sviluppo dell'applicazione myapp si chiama myapp_dev.log, mentre quello per l'ambiente di produzione si chiama myapp_prod.log, e così via.

Se stai facendo girare un'applicazione symfony, dai un'occhiata ai suoi file di log. La sintassi è molto semplice. Per ogni evento viene aggiunta una linea al file dell'applicazione. Ogni linea include l'ora esatta dell'evento, la sua natura, l'oggetto che viene processato, e qualche altro dettaglio importante. Il Listato 16-2 ne mostra un esempio.

Listato 16-2 - Esempio di file di log di symfony, in log/myapp_dev.php [php] Nov 15 16:30:25 symfony [info ] {sfAction} call "barActions->executemessages()" Nov 15 16:30:25 symfony [debug] SELECT bd_message.ID, bd_message.SENDER_ID, bd_... Nov 15 16:30:25 symfony [info ] {sfCreole} executeQuery(): SELECT bd_message.ID... Nov 15 16:30:25 symfony [info ] {sfView} set slot "leftbar" (bar/index) Nov 15 16:30:25 symfony [info ] {sfView} set slot "messageblock" (bar/mes... Nov 15 16:30:25 symfony [info ] {sfView} execute view for template "messa... Nov 15 16:30:25 symfony [info ] {sfView} render "/home/production/myproject/... Nov 15 16:30:25 symfony [info ] {sfView} render to client

Puoi trovare molti dettagli in questi file, incluse le query effettivamente spedite al db, le template chiamate, le catene di chiamate tra gli oggetti e così via.

Configurazione dei livelli di log di symfony

Esistono otto livelli per i messaggi di log di symfony: emerg, alert, crit, err, warning, notice, info, e debug, che sono gli stessi livelli del pacchetto PEAR::Log ([http://pear.php.net/package/Log/]). Puoi definire il massimo livello da loggare per ogni ambiente nel file di configurazione logging.yml di ogni applicazione, come mostrato nel Listato 16-3.

Listato 16-3 - Configurazione di default del logging, in myapp/config/logging.yml [php] prod: enabled: off level: err rotate: on purge: off

dev:

test:

#all:
#  enabled:  on
#  level:    debug
#  rotate:   off
#  period:   7
#  history:  10
#  purge:    on

Per default, in tutti gli ambienti tranne quello di produzione, tutti gli eventi vengono loggati (fino al minimo importante, il livello debug). Nell'ambiente di produzione, il logging è disabilitato per default; se imposti enabled a on, appariranno nel logo solo i messaggi più importanti (da crit a emerg).

Puoi cambiare il livello di logging nel file logging.yml per ogni ambiente per limitare il tipo di messaggi da loggare. Le impostazioni rotate, period, history, e purge saranno descritte più avanti nella sezione "Pulire e ruotare i file di log".

TIP I valori dei parametri di logging sono accessibili durante l'esecuzione tramite l'oggetto sfConfig con il prefisso sf_logging_. Ad esempio, per controllare se il logging è abilitato, chiama sfConfig::get('sf_ logging_enabled').

Aggiungere un messaggio di log

Puoi aggiungere un messaggio nei file di log di symfony usando una delle tecniche descritte nel Listato 16-4.

Listato 16-4 - Aggiungere un messaggio di log personalizzato

[php]
// Da un'azione
$this->logMessage($message, $level);

// Da una template
<?php use_helper('Debug') ?>
<?php log_message($message, $level) ?>

Alternativamente, per scrivere un messaggio di log da un qualsiasi punto della tua applicazione, usa il metodo sfLogger direttamente, come mostrato nel Listato 16-5. I metodi disponibili prendono lo stesso nome dei livelli di log.

Listato 16-5 - Aggiungere un messaggio di log da un qualsiasi punto

[php]
if (sfConfig::get('sf_logging_enabled'))
{
  sfContext::getInstance()->getLogger()->info($message);
}

SIDEBAR Personalizzare il logging

Il sistema di logging di symfony è molto semplice, per cui è anche semplice personalizzarlo. Puoi specificare il tuo oggetto di logging chiamando sfLogger::getInstance()->registerLogger(). Ad esempio, se volessi usare PEAR::Log, aggiungi il codice seguente al tuo config.php:

[php]
require_once('Log.php');
$log = Log::singleton('error_log', PEAR_LOG_TYPE_SYSTEM, 'symfony');
sfLogger::getInstance()->registerLogger($log);

Se vuoi registrare la tua classe di logging personalizzata, l'unico requisito è la definizione di un metodo log(). Symfony chiama tale metodo con due parametri: $message (il messaggio da loggare) e $priority (il livello).

Pulire e ruotare i file di log

Non dimenticare di pulire periodicamente la cartella log/ delle tue applicazioni, perché tali file hanno la strana abitudine di crescere di diversi megabyte al giorno, in relazione, ovviamente, al traffico. A tale scopo symfony fornisce un task log-purge, che puoi lanciare a mano od impostare in una tabella di cron. Ad esempio, il comando seguente elimina i file di log delle applicazioni in cui è specificato purge: on nel file logging.yml (che è il default):

> symfony log-purge

Sia per le prestazioni che per la sicurezza, probabilmente vorrai tenere i log di symfony in diversi piccoli file piuttosto che in un unico file di grandi dimensioni. La strategia di storage dei file di log ideale è di fare il backup per poi svuotare il file di log regolarmente, ma di mantenere un numero limitato di file di backup. Puoi abilitare questo tipo di rotazione e specificarne i parametri nel file logging.yml. Ad esempio, con un period di 7 giorni ed una history (numero di backup) di 10, come mostrato nel Listato 16-6, lavoreresti con un file di log attivo più 10 backup contenenti ognuno 7 giorni di log.

Listato 16-6 - Configurare la rotazione dei log, in myapp/config/logging.yml

prod:
  rotate:  on
  period:  7       ## Per default i file di log vengono ruotati ogni 7 giorni
  history: 10      ## Viene tenuto un massimo di 10 file di log come history

Per eseguire la rotazione, esegui periodicamente il task log-rotate. Questo comando elimina solo i file per cui rotate è on. Puoi specificare una singola applicazione ed ambiente chiamando:

> symfony log-rotate myapp prod

Il backup dei file di log viene tenuto nella cartella logs/history/, con un suffisso che indica la data in cui è stato fatto il backup.

Debugging

Non ha importanza quanto sei bravo nello sviluppo, prima o poi, anche se usi symfony, qualche errore lo commetterai. Trovare e capire gli errori è una delle chiavi dello sviluppo veloce di un'applicazione. Fortunatamente, symfony mette a disposizione diversi strumenti di debugging per lo sviluppatore.

Modalità di debug

Symfony possiede una modalità di debug per facilitare lo sviluppo ed il debug delle applicazioni. Quando è attivo, succede questo:

  • La configurazione viene controllata ad ogni richiesta, per cui qualsiasi cambiamento non richiede la pulizia della cache.
  • I messaggi di errore vengono visualizzati in modo chiaro ed utile, in modo che si possa trovare immediatamente il "colpevole".
  • Sono disponibili strumenti di debugging ulteriori quali ad esempio i dettagli delle query al db.
  • Anche la modalità di debug di Propel viene attivata, per cui qualsiasi errore in una chiamata Propel visualizzerà dettagliatamente la catena delle chiamate tramite l'architettura Propel.

D'altra parte, quando la modalità di debug non è attiva, il processo è gestito nel modo seguente:

  • I file di configurazione YAML vengono processati una volta sola, e poi trasformati in file PHP nella cartella cache/config/. Ogni richiesta successiva alla prima ignora i file YAML e consulta quelli in cache. Di conseguenza, il processo delle richieste è molto più veloce.
  • Per permettere nuovamente la consultazione dei file di configurazione, occorre pulire la cache.
  • Un errore durante l'esecuzione genera un codice 500 (Internal Server Error), senza alcune spiegazioni sulle cause.

La modalità di debug viene attivata per applicazione nel front controller. È controllata dal valore della costante SF_DEBUG, come mostrato nel Listato 16-7.

Listato 16-7 - Esempio di front controller con la modalità di debug attiva, in web/myapp_dev.php [php] <?php

define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'myapp');
define('SF_ENVIRONMENT', 'dev');
define('SF_DEBUG',       true);

require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');

sfContext::getInstance()->getController()->dispatch();

CAUTION Non dovresti attivare la modalità di debug sul server di produzione, e neppure lasciare la possibilità di farlo. Non solo peggiorerebbe le prestazioni, ma potrebbe anche rivelare le interna della tua applicazione, mettendone a rischio la sicurezza.

Le eccezioni di symfony

Quando capita un'eccezione in modalità di debug, symfony mostra un insieme di informazioni interessanti che aiutano a capire la causa del problema.

I messaggi di eccezione sono scritti chiaramente e si riferiscono alla causa più probabile del problema. Spesso suggeriscono anche una soluzione al problema, e per quelli più comuni c'è un link alla pagina del sito di symfony con maggiori dettagli sull'eccezione generata. Tramite la syntax highlighting viene mostrato il tratto di codice PHP che ha generato l'eccezione, e l'insieme delle chiamate ai metodi, come mostrato in Figura 16-1. Vengono mostrati anche gli argomenti passati ai metodi.

NOTE Symfony si basa veramente sulle eccezioni PHP per il report degli errori, che è molto meglio rispetto al modo in cui lavora PHP 4. Ad esempio, un errore 404 può essere triggerato tramite sfError404Exception.

Figura 16-1 - Esempio di eccezione di un'applicazione symfony

Esempio di eccezione di un'applicazione symfony

Durante la fase di sviluppo, le eccezioni symfony saranno di grande utilità per il debug.

L'estensione Xdebug

L'estensione Xdebug (http://xdebug.org/) permette di estendere le informazioni che vengono loggate dal web server. Symfony integra i messaggi di Xdebug nel proprio feedback, per cui è una buona idea attivare tale estensione durante il debug di un'applicazione. L'installazione dell'estensione dipende molto dalla piattaforma; consulta il sito di Xdebug per informazioni dettagliate al riguardo. Una volta che hai installato Xdebug, lo devi attivare nel file php.ini. Per le piattaforme *nix, questo si può fare aggiungendo la linea:

zend_extension="/usr/local/lib/php/extensions/no-debug-non-zts-20041030/xdebug.so"

mentre per le piattaforme Windows:

extension=php_xdebug.dll

Il Listato 16-8 mostra un esempio di configurazione di Xdebug, quale deve essere aggiunto nel file php.ini.

Listato 16-8 - Esempio di configurazione Xdebug ;xdebug.profiler_enable=1 ;xdebug.profiler_output_dir="/tmp/xdebug" xdebug.auto_trace=1 ; enable tracing xdebug.trace_format=0 ;xdebug.show_mem_delta=0 ; memory difference ;xdebug.show_local_vars=1 ;xdebug.max_nesting_level=100

Per poterla attivare devi infine riavviare il tuo web server.

CAUTION Non dimenticare di disattivare Xdebug sul tuo sistema in produzione. Altrimenti la velocità di esecuzione delle pagine ne soffrirà molto.

La toolbar Web Debug

I file di log contengono informazioni interessanti, ma non sono molto facili da leggere. Il compito più semplice, ovvero trovare le linee loggate per una richiesta particolare, può risultare difficoltoso se diversi utenti usano l'applicazione nello stesso momento e l'history del log è lunga. Ecco quando la web debug toolbar diventa utile.

Questa toolbar appare come un rettangolo semitrasparente nell'angolo in alto a destra del browser, come mostrato in Figura 16-2. Essa fornisce accesso agli eventi di log di symfony, alla configurazione corrente, alle proprietà della richiesta e gli oggetti della risposta, ai dettagli delle query eseguite sul db ed alle prestazioni.

Figura 16-2 - La web debug toolbar appare sull'angolo in alto a destra

La web debug toolbar appare sull'angolo in alto a destra

Il colore del background della toolbar dipende dal più alto livello dei messaggi di log durante la richiesta. Se non vi è alcun messaggio a livello debug, la toolbar rimane grigia. Se anche un solo messaggio raggiunge il livello err, la toolbar diventa rossa.

NOTE Non confondere la modalità di debug con la debug toolbar. Essa può essere visualizzata anche quando la modalità di debug è off, anche se in quel caso mostra molte meno informazioni.

Per attivare la web debug toolbar per un'applicazione, apri il file settings.yml e cerca la chiave web_debug. Negli ambienti prod e test, il suo valore di default è off, per cui se la desideri la devi attivare manualmente. Nell'ambiente dev, il valore di default è on, come mostrato nel Listato 16-9.

Listato 16-9 - Attivazione della web debug toolbar, in myapp/config/settings.yml

dev:
  .settings:
    web_debug:              on

Quando visualizzata, la toolbar offre una grande varietà di informazioni/interazioni:

  • Clicca sul logo di symfony per nasconderla; quando è nascosta, non copre gli elementi in quell'area della pagina.
  • Clicca la sezione vars & config per vedere i dettagli della richiesta, risposta, impostazioni e variabili PHP, come mostrato in Figura 16-3. La prima linea riassume le impostazioni più importanti della configurazione, come la modalità di debug, la cache, e la presenza di un acceleratore PHP (essi appaiono in rosso se disattivati, in verde se attivi).

Figura 16-3 - La sezione vars & config mostra tutte le variabili e costanti della richiesta

La sezione vars & config mostra tutte le variabili e costanti della richiesta

  • Quando la cache è abilitata, appare una freccia verde nella toolbar. Clicca tale freccia per riprocessare la pagina, ignorando la cache (la quale però non viene svuotata).
  • Clicca su logs & msg per vedere le informazioni dei file di log della richiesta corrente, come mostrato in Figura 16-4. A seconda dell'importanza degli eventi, esse saranno visualizzate in grigio, giallo o rosso. Puoi filtrare gli eventi visualizzati usando i link all'inizio della lista.

Figura 16-4 - La sezione logs & msg mostra i log per la richiesta corrente

La sezione logs & msg mostra i log per la richiesta corrente

NOTE Quando l'azione corrente è il risultato di un redirect, saranno presenti nel pannello solo i log dell'ultima richiesta, per cui i file di log sono ancora indispensabili per un buon debug.

  • Per le richieste che eseguono query SQL, nella toolbar appare l'icona di un database. Cliccala per vedere i dettagli delle query, come mostrato in Figura 16-5.
  • Alla destra dell'orologio c'è il tempo totale necessario a processare la richiesta. Ricorda che la web debug toolbar e la modalità di debug rallentano l'esecuzione delle richieste, per cui evita di considerare tali valori in se e confronta l'esecuzione fra due pagine. Clicca sull'orologio per vedere i dettagli del tempo di processione per categoria, come mostrato in Figura 16-6. Symfony visualizza il tempo speso su parti specifiche della richiesta. Solo i tempi relativi alla richiesta corrente hanno senso per l'ottimizzazione, per cui il tempo nel core di symfony non viene visualizzato. Ecco perché tale valore non è la somma del tempo totale.
  • Clicca sulla X rossa a destra per chiuderla.

Figura 16-5 - La sezione del db mostra le query eseguite per la richiesta corrente

La sezione del db mostra le query eseguite per la richiesta corrente

Figura 16-6 - L'icona dell'orologio mostra i tempi di esecuzione per categoria

L'icona dell'orologio mostra i tempi di esecuzione per categoria

SIDEBAR Aggiungere il tuo timer Symfony usa la classe sfTimer per calcolare il tempo utilizzato nella configurazione, nel modello, azione e vista. Utilizzando lo stesso oggetto, puoi calcolare un processo custom e visualizzare il risultato con gli altri timer nella web debug toolbar. Questo può risultare molto utile quando lavori sull'ottimizzazione delle performance.

Per inizializzare il timing su uno specifico frammento di codice, chiama il metodo getTimer(). Esso restituirà un oggetto sfTimer e comincerà il calcolo. Chiama il metodo addTime() su tale oggetto per fermare il calcolo. Il tempo necessario sarà disponibile tramite il metodo getElapsedTime(), e visualizzato nella toolbar insieme agli altri.

[php]
// Initialize the timer and start timing
$timer = sfTimerManager::getTimer('myTimer');

// Do things
...

// Stop the timer and add the elapsed time
$timer->addTime();

// Get the result (and stop the timer if not already stopped)
$elapsedTime = $timer->getElapsedTime();

Il beneficio derivante dal dare un nome od ogni timer è quello di poter accumulare i timing. Ad esempio, se il timer myTimer viene utilizzato in una utility chiamata due volte a richiesta, la seconda chiamata a getTimer('myTimer') farà ripartire il timing dall'ultimo punto in cui è stato chiamato il metodo addTime(), sommando. Chiamando getCalls() sull'oggetto timer troverai il numero di volte in cui un timer è stato lanciato, ed anche tale informazione viene visualizzata nella toolbar.

[php]
// Get the number of calls to the timer
$nbCalls = $timer->getCalls();

In modalità Xdebug, i messaggi di log sono molto più ricchi. Tutti gli script PHP e le funzioni chiamate vengono loggate, e symfony sa come collegare tale informazioni con i propri log interni. Ogni linea dei messaggi di log finisce con un pulsante con una doppia freccia, che puoi cliccare per vedere più informazioni sulla richiesta relativa. Se qualcosa andasse male, la modalità Xdebug ti fornisce la maggior quantità possibile di dettagli per capire dove e come.

NOTE La web debug toolbar non è inclusa per default in risposte Ajax e documenti che non abbiano un content-type HTML. Per le altre pagine, puoi disabilitare la toolbar manualmente da dentro un'azione chiamando semplicemente sfConfig::set('sf_web_debug', false).

Debugging manuale

Avere accesso ai messaggi del framework di debug è carino, ma è meglio avere la capacità di loggare i tuoi propri messaggi. Symfony mette a disposizione dei collegamenti, disponibili sia nelle template che nelle azioni, per tenere traccia dei tuoi eventi durante l'esecuzione.

I tuoi messaggi di log appaiono sia nei file di log di symfony sia nella toolbar, esattamente come gli eventi normali. (Il Listato 16-4 ne mostrava la sintassi) Un messaggio personalizzato è un buon modo di controllare il valore di una variabile in una template, ad esempio. Il Listato 16-10 mostra come usare la web debug toolbar per il feedback dello sviluppatore dalla template (da un'azione puoi usare $this->logMessage()).

Listato 16-10 - Inserire un messaggio nel log per il debugging

[php]
<?php use_helper('Debug') ?>
...
<?php if ($problem): ?>
  <?php log_message('{sfAction} been there', 'err') ?>
  ...
<?php endif ?>

L'utilizzo del livello err garantisce che il messaggio sarà chiaramente visibile nella lista dei messaggi, come mostrato in Figura 16-7.

Figura 16-7 - Un messaggio personalizzato appare nella sezione logs & msgs della web debug toolbar

Un messaggio personalizzato appare nella sezione logs & msgs della web debug toolbar

Se tu non volessi aggiungere una linea al log, ma semplicemente tracciare un valore, dovresti usare debug_message invece di log_message. Tale metodo (esiste anche un helper con lo stesso nome) visualizza un messaggio nella toolbar, all'inizio della sezione logs & msgs. Controlla il Listato 16-11 per un esempio.

Listato 16-11 - Inserire un messaggio nella web debug toolbar

[php]
// From an action
$this->debugMessage($message);

// From a template
<?php use_helper('Debug') ?>
<?php debug_message($message) ?>

Popolare un database

Nel processo di sviluppo di un'applicazione, spesso gli sviluppatori devono affrontare la problematica della popolazione di un db. Esiste qualche soluzione specifica, ma nessuna che possa essere usata in generale sulla base di un E/R. Grazie all'oggetto sfPropelData ed a YAML, symfony può trasferire automaticamente dati da un file di testo ad un database. Anche se potrebbe sembrare che scrivere un file di testo necessiti di più tempo che utilizzare un'interfaccia CRUD, alla fine noterai che invece ne risparmi.

Sintassi di file fixture

Symfony può leggere file di dati che seguano una sintassi YAML molto semplice, presupposto che tali file siano situati nella cartella data/fixtures/. I file fixture sono organizzati in classi, ogni sezione di una classe comincia con il nome della classe ed un header. Per ogni classe, i record chiamati con un nome unico sono identificati da coppie fieldname: value. Il Listato 16-12 mostra un esempio di file di dati per la popolazione.

Listato 16-12 - Esempio di file fixture, in data/fixtures/import_data.yml

Article:                             ## Insert records in the blog_article table
  first_post:                        ## First record label
    title:       My first memories
    content: |
      For a long time I used to go to bed early. Sometimes, when I had put
      out my candle, my eyes would close so quickly that I had not even time
      to say "I'm going to sleep."

  second_post:                       ## Second record label
    title:       Things got worse
    content: |
      Sometimes he hoped that she would die, painlessly, in some accident,
      she who was out of doors in the streets, crossing busy thoroughfares,
      from morning to night.

Symfony traduce le colonne chiavi in metodi setter utilizzando un convertitore camelCase (setTitle(), setContent()). Ciò significa ad esempio che tu potresti definire una chiave password anche se effettivamente nella tabella un campo password non esiste; dovresti solo definire un metodo setPassword() nell'oggetto User, potendo così popolare le altre colonne basandoti sulla password (ad esempio, una sua versione hash).

Le chiavi primarie non hanno bisogno di essere definite. Dato che sono campi auto-increment, il database sa come comportarsi.

Anche le colonne created_at non ne hanno bisogno, perché symfony sa che i campi che si chiamano in quel modo devono essere impostati con l'ora corrente.

Lanciare l'importazione

Il task propel-load-data importa i dati dal file YAML al database. Le impostazioni di connessione vengono dal file databases.yml, perciò c'è bisogno di un nome di applicazione per farlo girare. Opzionalmente puoi specificare un ambiente (dev è il default).

> symfony propel-load-data frontend

Questo comando legge tutti i file fixture nella cartella data/fixtures/ ed inserisce i record nel db. Per default, esso sostituisce i dati esistenti, ma se l'ultimo argomento della chiamata è append, il comando aggiungerà i dati.

> symfony propel-load-data frontend append

Puoi anche specificare un altro file fixture o cartella nella chiamata. In questo caso, aggiungi un path relativo alla cartella data/ del progetto.

> symfony propel-load-data frontend data/myfixtures/myfile.yml

Usare tabelle collegate

Ora sai come importare dati in tabelle singole, ma come funziona con chiavi importate? Dato che le chiavi primarie non sono incluse nelle fixture, c'è bisogno di un modo alternativo.

Torniamo all'esempio del Capitolo 8, dove la tabella blog_article è collegata alla blog_comment, come mostrato in Figura 16-8.

Figura 16-8 - Esempio di modello database relazionale

Esempio di modello database relazionale

Ecco dove le etichette date ai record risultano veramente utili. Per aggiungere un campo Comment all'articolo first_post, devi solo aggiungere le linee del Listato 16-13 al file import_data.yml.

Listato 16-13 - Aggiungere record ad una tabella collegata, in data/fixtures/import_data.yml

Comment:
  first_comment:
    article_id:   first_post
    author:       Anonymous
    content:      Your prose is too verbose. Write shorter sentences.

Il task propel-load-data riconoscerà la label che avevi precedentemente dato ad un articolo nel file import_data.yml, per cui rintraccerà la chiave primaria del corrispondente record nella tabella Article per impostare il campo article_id. Non vedrai nemmeno gli ID dei record; li collegherai tramite le label, ciò non potrebbe essere più semplice.

L'unico vincolo per i record collegati è che gli oggetti chiamati nelle chiavi importate devono essere definiti prima nel file; che è poi quello che faresti se li definissi uno a uno. I file dati vengono parsati dall'alto al basso, per cui è importante l'ordine in cui sono scritti i record.

Un file dati può contenere le dichiarazioni di diverse classi. Ma se hai bisogno di inserire molti dati per diverse tabelle, il tuo file fixture potrebbe diventare troppo lungo e non facile da manipolare.

Il task propel-load-data parsa tutti i file della cartella fixtures/, per cui potresti suddividere i file YAML in parti più piccole. L'unica cosa da tenere a mente è l'ordine per le chiavi importate, per cui per essere sicuro di preservarlo puoi ad esempio aggiungere un prefisso numerico ai file.

100_article_import_data.yml
200_comment_import_data.yml
300_rating_import_data.yml

Distribuire applicazioni

Symfony offre comandi veloci per sincronizzare due versioni di un sito web. Tali comandi vengono principalmente usati per fare il deploy di un sito da un server di sviluppo ad uno di produzione, connesso ad Internet.

Congelamento di un progetto per il trasferimento tramite FTP

Il modo più comune per il deploy di un sito in produzione è quello di trasferire tutti i suoi file tramite FTP (o SFTP). Ad ogni modo, i progetti symfony usano le proprie librerie, ed a meno di sviluppare in una sandbox (che non è consigliato), o se le cartelle lib/ e data/ sono collegate tramite svn:externals, tali directory non si trovano nella cartella del progetto. Sia utilizzando la PEAR che link simbolici, riprodurre la stessa struttura di cartelle può richiedere tempo.

Ecco perché symfony fornisce una utility per "congelare" un progetto, ovvero per copiare le necessarie librerie nelle cartelle del progetto data/, lib/ e web/. In tal modo il progetto diventa come una sandbox, un'applicazione stand-alone.

> symfony freeze

Una volta che il progetto è congelato, puoi trasferire la cartella del progetto in produzione, e tutto funzionerà senza bisogno di PEAR, link simbolici o quant'altro.

TIP Diversi progetti congelati possono funzionare sullo stesso server con diverse versioni di symfony senza alcun problema.

Per riportare un progetto al suo stato iniziale, usa il comando unfreeze. Esso elimina le cartelle data/symfony/, lib/symfony/ e web/sf/.

> symfony unfreeze

Nota che se tu avessi avuto link simbolici in un'installazione symfony prima del congelamento, symfony se lo ricorderebbe e li ripristinerebbe nella loro posizione originale.

Usare rsync per il trasferimento incrementale

Inviare la cartella di root di un progetto via FTP per il primo trasferimento va bene, ma quando hai bisogno di aggiornare la tua applicazione con un update dove solo alcuni file sono cambiati, tale metodo non è ideale. Dovresti caricare di nuovo tutto il progetto, con spreco di tempo e banda, oppure cercare nel progetto solo i file modificati e trasferirli. Ciò è un lavoro noioso e incline ad errori. Inoltre, il sito in produzione potrebbe risultare, durante il trasferimento, non disponibile o con bug.

La soluzione supportata da symfony è una sincronizzazione via rsync tramite un layer SSH. Rsync (http://samba.anu.edu.au/rsync/) è una utility a linea di comando che fornisce un trasferimento incrementale veloce, ed è open source. Tramite il trasferimento incrementale, solo i file modificati verranno inviati; quelli che non sono cambiati non saranno spediti al server in produzione. Se un file è stato cambiato parzialmente, solo tale parte verrà inviata. Il vantaggio principale di questa tecnica è quindi che solo piccole porzioni di dati verranno spediti, ed il procedimento risulterà molto veloce.

Symfony aggiunge SSH alla sincronizzazione rsync per la sicurezza del trasferimento. Sempre più hosting commerciali mettono a disposizione un tunnel SSH per avere upload sicuri sui propri server, e questo è una buona pratica per evitare falle di sicurezza.

Il client SSH chiamato da symfony utilizza le impostazioni di connessione specificate nel file config/properties.ini. Il Listato 16-14 mostra un esempio di impostazioni di connessione per un server di produzione. Scrivi le impostazioni del tuo server di produzione in tale file prima di qualsiasi sincronizzazione.

Listato 16-14 - Esempio di impostazioni di connessione per una sincronizzazione con un server, in myproject/config/properties.ini

[symfony]
  name=myproject

[production]
  host=myapp.example.com
  port=22
  user=myuser
  dir=/home/myaccount/myproject/

NOTE Non confondere il server di produzione (il server host, come definito nel file properties.ini del progetto) con l'ambiente di produzione (il front controller e la configurazione usata in produzione, come riportato nei file di configurazione di un'applicazione).

Eseguire un rsync su SSH richiede diversi comandi, e la sincronizzazione può ricorrere molte volte nella vita di un'applicazione. Fortunatamente, symfony automatizza tale processo con un semplice comando:

> symfony sync production

Questo comando esegue rsync in dry mode; ciò significa che mostra quali file dovrebbero essere sincronizzati senza farlo veramente. Se vuoi effettivamente eseguire la sincronizzazione, devi esplicitarlo aggiungendo go.

> symfony sync production go

Non dimenticare di pulire la cache del server di produzione dopo una sincronizzazione.

TIP Alcune volte compaiono dei bug in produzione che non sono invece presenti in sviluppo. Nel 90% dei casi, ciò è dovuto a differenze nelle versioni (di PHP, web server o database) o nelle configurazioni. Per evitare spiacevoli sorprese, dovresti definire la configurazione di PHP del file php.yml della tua applicazione, in modo che venga controllato che l'ambiente di sviluppo applichi le stesse impostazioni. Consulta il Capitolo 19 per maggiori informazioni in merito.

-

SIDEBAR La tua applicazione è completata? Prima di spedire la tua applicazione in produzione, dovresti accertarti che sia pronta per l'utilizzo pubblico. Controlla che le seguenti cose siano effettivamente state fatte prima di fare il deploy:

Le pagine di errore dovrebbero essere personalizzate con il look and feel della tua applicazione. Consulta il Capitolo 19 per capire come personalizzare gli errori 500, 404 e le pagine di sicurezza, e la sezione "Gestire un'applicazione in produzione" più avanti in questo capitolo per vedere come personalizzare le pagine mostrate quando il tuo sito non è disponibile.

Il modulo default dovrebbe essere rimosso dall'array enabled_modules in settings.yml, in modo che non appaiano pagine symfony per errore.

Il meccanismo di gestione delle sessioni usa un cookie lato client, e tale cookie si chiama symfony per default. Prima di fare il deploy, dovresti probabilmente rinominarlo per evitare di mostrare che la tua applicazione si basa su symfony. Controlla il Capitolo 6 per vedere come personalizzare il nome del cookie nel file factories.yml.

Il file robots.txt, situato nella cartella web/ del progetto, è vuoto per default. Dovresti personalizzarlo per informare gli spider web ed altri robot di quale parte del sito dovrebbero navigare e quale dovrebbero evitare. La maggior parte delle volte, tale file viene usato per evitare di indicizzare certi URL space, ad esempio pagine che richiedono molte risorse, pagine che non ne abbiano bisogno (come archivi di bug), o URL space infiniti dove i robot potrebbero rimanere intrappolati.

I browser moderni richiedono un file favicon.ico quando un utente naviga per la prima volta il tuo sito, per rappresentare la tua applicazione con un'icona nella barra degli indirizzi e nei bookmark. Fornire tale file non solo completerà il look and feel della tua applicazione, ma eviterà anche la presenza di errori 404 nei file di log del server.

Ignorare file irrilevanti

Se sincronizzi il tuo progetto symfony con un host di produzione, alcuni file e cartelle dovrebbero non essere inviate:

  • Tutte le cartelle di versioning (.svn/, CVS/ e così via) ed il loro contenuto sono necessari solo per lo sviluppo e l'integrazione.
  • Il front controller e l'ambiente di sviluppo non devono essere disponibili all'utente finale. Gli strumenti di debugging e di logging disponibili durante l'utilizzo dell'applicazione tramite tale controller rallentano ne rallentano l'esecuzione e forniscono informazioni sulle variabili di core delle tue azioni. E' qualcosa da tenere lontano dal pubblico.
  • Le cartelle cache/ e log/ di un progetto non devono venire cancellate sul server di produzione ad ogni sincronizzazione. Anche queste cartelle devono essere ignorate. Se hai una cartella stats/, probabilmente dovrebbe essere trattata nello stesso modo.
  • I file caricati dagli utenti non devono essere trasferiti. Una delle buone pratiche dei progetti symfony è quella di tenere i file caricati nella cartella web/uploads/. Questo ti permette di escludere tali file dalla sincronizzazione puntando ad una sola cartella.

Per escludere file dalla sincronizzazione rsync, apri e modifica il file rsync_exclude.txt nella cartella myproject/config/. Ogni linea può contenere un nome di file, di directory od un pattern. La struttura di file di symfony è organizzata logicamente, e disegnata per minimizzare il numero di file e cartelle da escludere manualmente da una sincronizzazione. Vedi il Listato 16-15 per un esempio.

Listato 16-15 - Esempio di impostazione di esclusione rsync, in myproject/config/rsync_exclude.txt

.svn
/cache/*
/log/*
/stats/*
/web/uploads/*
/web/myapp_dev.php

NOTE Le cartelle cache/ e log/ non devono essere sincronizzate con il server di sviluppo, ma devono almeno esistere sul server di produzione. Creale a mano se non sono già presenti nella cartella myproject/.

Gestire un'applicazione in produzione

Il comando usato più spesso in server di produzione è clear-cache. Lo devi eseguire ogni qualvolta aggiorni symfony od il tuo progetto (ad esempio tramite il comando sync), ed ogni volta che cambi la configurazione di produzione.

> symfony clear-cache

TIP Se l'interfaccia a linea di comando non fosse disponibile sul tuo server di produzione, puoi ancora pulire la cache manualmente cancellando il contenuto della cartella cache/.

Puoi disabilitare temporaneamente la tua applicazione, ad esempio quando devi aggiornare una libreria od una grande quantità di dati.

> symfony disable APPLICATION_NAME ENVIRONMENT_NAME

Per default, un'applicazione disabilitata mostra l'azione default/unavailable (memorizzata nel framework), ma puoi personalizzare il metodo e l'azione da usare in questo caso nel file settings.yml. Il Listato 16-16 ne mostra un esempio.

Listato 16-16 - Impostare un'azione da eseguire in caso di applicazione disabilitata, in myapp/config/settings.yml

all:
  .settings:
    unavailable_module:     mymodule
    unavailable_action:     maintenance

Il comando enable riabilita l'applicazione e pulisce la cache.

> symfony enable APPLICATION_NAME ENVIRONMENT_NAME

SIDEBAR Visualizzare una pagina non disponibile mentre si pulisce la cache Se imposti il parametro check_lock a on nel file settings.yml, symfony bloccherà l'applicazione durante la pulizia della cache, e tutte le richieste che arriveranno prima che la pulizia sia stata completata, verranno ridirezionate su una pagina che dice che l'applicazione è temporaneamente non disponibile. Se la cache è molto ampia, il ritardo necessario potrebbe essere maggiore di qualche millisecondo, e se il traffico sul tuo sito è alto questa è un'impostazione consigliata.

Questa pagina che mostra il messaggio di non disponibile non è la stessa di quella visualizzata quando chiami symfony disable (in quanto durante la pulizia della cache symfony non funziona normalmente). Essa è situata nella cartella $sf_symfony_data_dir/web/errors/, ma puoi creare il tuo file unavailable.php nella directory web/errors/ del progetto, e symfony la userà. Il parametro check_lock è disattivato per default perché ha un impatto molto negativo sulle performance.

Il comando clear-controllers pulisce la cartella web/ da tutti i controller che non siano quelli che girano in produzione. Se non includi il controller di sviluppo nel file rsync_exclude.txt, questo comando evita che una backdoor riveli gli interni della tua applicazione.

> symfony clear-controllers

I permessi dei file e cartelle di progetto possono essere violati se usi un checkout da un repository SVN. Il comando fix-perms rimette a posto i permessi, ad esempio per cambiare i permessi di cache/ e log/ in 0777 (tali cartelle hanno bisogno di essere scrivibili dal framework per funzionare correttamente).

> symfony fix-perms

SIDEBAR Accesso ai comandi symfony in produzione Se il tuo server di produzione ha un'installazione PEAR di symfony, allora la linea di comando sarà disponibile da qualsiasi cartella e funzionerà esattamente come in sviluppo. Comunque, per i progetti congelati, devi aggiungere php prima del comando symfony per poter lanciare i comandi:

// With symfony installed via PEAR
> symfony [options] <TASK> [parameters]

// With symfony frozen in the project or symlinked
> php symfony [options] <TASK> [parameters]

Sommario

Combinando i log di PHP e di symfony, puoi facilmente monitorare e debuggare le tue applicazioni. Durante lo sviluppo, la modalità di debug, le eccezioni, e la web debug toolbar ti aiutano a trovare i problemi. Puoi anche inserire messaggi personalizzati nei file di log o nella toolbar per facilitare il debug.

L'interfaccia a linea di comando fornisce un grande numero di strumenti che facilitano la gestione delle tue applicazioni, durante le fasi di sviluppo e di produzione. Soprattutto, il popolamento dei dati, il congelamento e la sincronizzazione fanno risparmiare molto tempo.