Di Fabien Potencier
L'utilizzo di symfony è già di per se un ottimo modo per aumentare la propria produttività come sviluppatore web. Naturalmente, tutti sanno che nell'ambiente di sviluppo le eccezioni di symfony o la barra web degli strumenti per il debug, permettono di migliorare notevolmente la produttività. Questo capitolo insegnerà alcuni trucchi e suggerimenti per migliorare ancora di più la produttività, mediante l'utilizzo di alcune nuove o meno conosciute funzionalità di symfony.
Iniziare più velocemente: personalizzare il processo di creazione del progetto
Grazie allo strumento CLI di symfony, la creazione di un nuovo progetto symfony è veloce come può esserlo digitare il seguente comando:
$ php /path/to/symfony generate-project foo --orm=Doctrine
Il task generate:project
genera la struttura predefinita delle cartelle per
il nuovo progetto e crea i file di configurazione con valori predefiniti. Ora
si possono usare altri task di symfony per creare applicazioni, installare plugin,
configurare il modello e altro.
Ma i primi passi per creare un nuovo progetto sono probabilmente sempre gli stessi: si crea una applicazione principale, si installa un gruppo di plugin, si modificano a proprio piacimento alcune configurazioni predefinite e così via.
Da symfony 1.3 il processo di creazione di un progetto può essere personalizzato e automatizzato.
note
Siccome tutti i task di symfony sono classi, è piuttosto facile personalizzarli
ed estenderli, escluso però il task generate:project
. Questo perché quando il task
è eseguito, non esiste ancora nessun progetto e così non esiste un modo semplice
per personalizzarlo.
Il task generate:project
prende una opzione --installer
che è uno script PHP
che verrà eseguito durante il processo di creazione del progetto:
$ php /path/to/symfony generate:project --installer=/somewhere/my_installer.php
Lo script /somewhere/my_installer.php
verrà eseguito nel contesto dell'istanza
di sfGenerateProjectTask
, quindi ha accesso a tutti i metodi che gli permettono
di eseguire il proprio lavoro (richiamandoli tramite l'oggetto $this
). Le
seguenti sezioni descrivono tutti i metodi disponibili che si possono utilizzare
per personalizzare il processo di creazione del progetto.
tip
Se nel php.ini
si attiva l'accesso URL ai file per la funzione include()
,
si può anche passare una URL come programma di installazione (naturalmente
è necessario stare molto attenti quando si fa questo con uno script di cui non si sa nulla):
$ symfony generate:project --installer=http://example.com/sf_installer.php
installDir()
Il metodo installDir()
copia una struttura di cartelle (composte da
sottocartelle e file) nel progetto appena creato:
$this->installDir(dirname(__FILE__).'/skeleton');
runTask()
Il metodo runTask()
esegue un task. Prende il nome del task e una stringa
che rappresenta i parametri e le opzioni che si desiderano passare a esso
come parametri:
$this->runTask('configure:author', "'Fabien Potencier'");
I parametri e le opzioni possono essere passati come array:
$this->runTask('configure:author', array('author' => 'Fabien Potencier'));
tip
I nomi scorciatoia dei task funzionano come ci si aspetta:
[php] $this->runTask('cc');
Questo metodo naturalmente può essere utilizzato per installare plugin:
$this->runTask('plugin:install', 'sfDoctrineGuardPlugin');
Per installare la versione specifica di un plugin, basta passare le opzioni necessarie:
$this->runTask('plugin:install', 'sfDoctrineGuardPlugin', array('release' => '10.0.0', 'stability' => beta'));
tip
Per eseguire un task da un plugin appena installato, i task devono prima essere ricaricati:
$this->reloadTasks();
Logger
Quando viene eseguito lo script di installazione, per dare un riscontro allo sviluppatore, si può registrare quello che succede nei log, in modo abbastanza semplice:
// un semplice log $this->log('Messaggi di installazione'); // log di un blocco $this->logBlock(array('', 'Il programma di installazione matto di Fabien', ''), 'ERROR'); // log in una sezione $this->logSection('install', 'installa alcuni file matti');
Interazione con l'utente
I metodi askConfirmation()
, askAndValidate()
e ask()
consentono di porre
domande e rendere il processo di installazione configurabile dinamicamente.
Se si ha solo bisogno di una conferma, si può utilizzare il metodo askConfirmation()
:
if (!$this->askConfirmation('Sei sicuro di voler eseguire questo matto programma di installazione?')) { $this->logSection('install', 'Hai fatto la scelta giusta!'); return; }
È inoltre possibile fare qualsiasi domanda e ottenere dagli utenti risposte
sotto forma di stringhe, utilizzando il metodo ask()
:
$secret = $this->ask('Dammi una stringa per il codice CSRF:');
Se si desidera validare la risposta, si può usare il metodo askAndValidate()
:
$validator = new sfValidatorEmail(array(), array('invalid' => 'hmmm, non sembra una email!')); $email = $this->askAndValidate('Per favore, dammi la tua email:', $validator);
Operazioni sul filesystem
Se si vogliono fare delle modifiche nel filesystem, è possibile accedere all'oggetto filesystem di symfony:
$this->getFilesystem()->...();
Lo script di installazione è un file PHP come gli altri. Quindi, può fare qualunque cosa si voglia. Quando si crea un nuovo progetto symfony, invece di eseguire continuamente sempre gli stessi task, è possibile creare il proprio script di installazione e modificare l'installazione per il proprio progetto di symfony nel modo desiderato. Creare un nuovo progetto con un programma di installazione è molto più rapido e inoltre evita di dimenticarsi di alcuni passi. Si possono anche condividere i propri script di installazione con quelli degli altri!
Sviluppare più velocemente
Dal codice PHP, ai task che utilizzano la CLI, la programmazione richiede molta digitazione. Vediamo come ridurre questa quantità al minimo indispensabile.
Scegliere un programma IDE
Usare un IDE aiuta lo sviluppatore a essere più produttivo in molti modi.
In primo luogo, i più moderni IDE forniscono il completamento del codice. Questo significa che è sufficiente digitare i primi caratteri del nome di un metodo; ma significa anche che se non si ricorda il nome di un metodo, non si è costretti a consultare le API, perché l'IDE proporrà tutti i metodi disponibili dell'oggetto corrente.
Poi, alcuni di essi, come PHPEdit o Netbeans, conoscono symfony e forniscono una integrazione più specifica con i progetti di symfony.
Utilizzare un IDE che supporta symfony
Alcuni IDE, come PHPEdit 3.4 e NetBeans 6.8, hanno un supporto nativo a symfony, quindi forniscono una integrazione specifica con il framework. Per saperne di più, sul loro supporto specifico per symfony e su come possono aiutare a sviluppare più velocemente, dare un'occhiata alla loro documentazione specifica.
Aiutare l'IDE
Negli IDE, l'autocompletamento del PHP funziona solo per i metodi che sono definiti
esplicitamente nel codice PHP. Ma se il codice utilizza i metodi
__call()
o __get()
"magic", gli IDE non hanno modo di capire i metodi o le proprietà
disponibili. La buona notizia è che si può aiutare l'IDE fornendo i metodi e/o le proprietà
in un blocco PHPDoc (utilizzando rispettivamente le annotazioni @method
e @property
).
Supponiamo di avere una classe Message
con una proprietà dinamica (message
) e
un metodo dinamico (getMessage()
). Il seguente codice mostra come un IDE può
venirne a conoscenza senza che ci sia una definizione esplicita nel codice PHP:
/** * @property clob $message * * @method clob getMessage() Restituisce il valore corrente di message */ class Message { public function __get() { // ... } public function __call() { // ... } }
Anche se il metodo getMessage()
non esiste, sarà riconosciuto dall'IDE, grazie
alla annotazione @method
. Lo stesso discorso vale per la proprietà message
perché è stata aggiunta l'annotazione @property
.
Questa tecnica è usata dal task doctrine:build-model
. Per esempio, una
classe MailMessage
di Doctrine, con due colonne (message
e property
)
risulterebbe così:
/** * BaseMailMessage * * This class has been auto-generated by the Doctrine ORM Framework * * @property clob $message * @property integer $priority * * @method clob getMessage() Returns the current record's "message" value * @method integer getPriority() Returns the current record's "priority" value * @method MailMessage setMessage() Sets the current record's "message" value * @method MailMessage setPriority() Sets the current record's "priority" value * * @package ##PACKAGE## * @subpackage ##SUBPACKAGE## * @author ##NAME## <##EMAIL##> * @version SVN: $Id: Builder.php 6508 2009-10-14 06:28:49Z jwage $ */ abstract class BaseMailMessage extends sfDoctrineRecord { public function setTableDefinition() { $this->setTableName('mail_message'); $this->hasColumn('message', 'clob', null, array( 'type' => 'clob', 'notnull' => true, )); $this->hasColumn('priority', 'integer', null, array( 'type' => 'integer', )); } public function setUp() { parent::setUp(); $timestampable0 = new Doctrine_Template_Timestampable(); $this->actAs($timestampable0); } }
Trovare velocemente la documentazione
Dal momento che symfony è un framework con molte caratteristiche, non è sempre facile ricordare tutte le possibili configurazioni, o tutte le classi e i metodi che si hanno a disposizione. Come abbiamo visto prima, utilizzando un IDE si ha un grande aiuto grazie all'autocompletamento. Vediamo come sfruttare gli strumenti esistenti per trovare le risposte il più velocemente possibile.
API online
Il modo più veloce per trovare la documentazione di una classe o di un metodo è quello di navigare online nelle API.
Di maggiore interesse è il motore di ricerca integrato nelle API. Esso consente di trovare rapidamente una classe o un metodo con poche battiture sulla tastiera. Nella pagina delle API, basta inserire alcune lettere nella casella di ricerca e apparirà una finestra in tempo reale con suggerimenti utili.
È possibile cercare digitando l'inizio del nome di una classe:
o del nome di un metodo:
o del nome di una classe seguito da ::
per elencare tutti i metodi disponibili:
o iniziare a scrivere il nome di un metodo per restringere ulteriormente le possibilità:
Se si desidera elencare tutte le classi di un pacchetto, è sufficiente digitare il nome del pacchetto e inviare la richiesta.
Si può anche integrare la ricerca delle API di symfony nel proprio browser. In questo modo non c'è nemmeno bisogno di passare dal sito web di symfony per cercare qualcosa. Questo è possibile perché forniamo un supporto nativo OpenSearch per le API di symfony.
Se si utilizza Firefox, il motore di ricerca delle API di symfony apparirà automaticamente nel menù dei motori di ricerca. Si può anche fare un click sul link "API OpenSearch" presente nella sezione con la documentazione delle API, per aggiungerle nella casella di ricerca del browser.
note
Nel blog di symfony, si può dare un'occhiata a uno screencast che mostra come il motore di ricerca delle API si symfony ben si integri con Firefox.
Cheat Sheet
Se può interessare avere alcuni fogli sintetici sulle principali parti del framework, si possono scaricare molti cheat sheets:
- Struttura delle cartelle e CLI
- View
- View: partial, componenti, slot e componenti slot
- Lime: test unitari e funzionali
- ORM
- Propel
- Schema di Propel
- Doctrine
note
Alcuni di questi cheat sheet non sono ancora stati aggiornati per symfony 1.3.
Documentazione offline
Le migliori risposte relative alle domande sulla configurazione, si trovano sulla guida di riferimento a symfony. Questo è un libro che bisogna tenersi vicini quando si sviluppa con symfony. È il modo più veloce per trovare ogni configurazione disponibile, grazie a un indice dei contenuti molto dettagliato, un indice dei termini, dei riferimenti incrociati all'interno dei capitoli, tabelle e molto altro ancora.
È possibile leggere questo libro online, comprarne una versione stampata (disponibile anche in italiano), , o scaricare una versione in PDF (solo in inglese).
Strumenti online
Come si è visto all'inizio di questo capitolo, symfony fornisce un insieme di strumenti che aiutano a procedere velocemente. Dopo qualche tempo, il progetto verrà completato e bisognerà metterlo in produzione.
Per verificare che il progetto è pronto per la messa in produzione, si può utilizzare l'elenco delle cose da verificare. Questo sito web mostra i punti più importanti che necessitano di verifica prima di poter andare in produzione.
Eseguire il debug più rapidamente
Quando si verifica un errore nell'ambiente di sviluppo, symfony mostra una
piacevole pagina con l'eccezione, che contiene molte informazioni utili.
È possibile, ad esempio, guardare lo stack trace e i file che sono stati eseguiti.
Se si imposta la configurazione sf_file_link_format
nel file settings.yml
(vedere sotto) si può anche fare clic sul nome del file e il file relativo sarà
aperto nella riga di destra nel proprio editor di testo o IDE. Questo è davvero
un buon esempio di una caratteristica davvero piccola, che però può fare
risparmiare una enormità di tempo quando si fa il debug.
note
I pannelli di log e di view mostrano anche i nomi dei file (in particolare quando XDebug
è abilitato) e questi nomi di file diventano cliccabili quando si imposta
l'impostazione sf_file_link_format
.
Per impostazione predefinita, sf_file_link_format
è vuoto e symfony si rifà al
alore della xdebug.file_link_format
configurazione PHP se esiste (l'impostazione xdebug.file_link_format
nel
php.ini
permette alle versioni recenti di XDebug di aggiungere link a tutti i
nomi dei file presenti nello stack trace).
Il valore per sf_file_link_format
dipende dall'IDE e dal sistema operativo.
Per esempio, se si vogliono aprire file in TextMate, aggiungere il seguente
frammento a settings.yml
:
dev: .settings: file_link_format: txmt://open?url=file://%f&line=%l
Il segnaposto %f
è sostituito da symfony con il percorso assoluto del file
e il segnaposto %l
è sostituito con il numero di linea.
Per chi usa VIM, la configurazione è più complicata ed è descritta online per symfony e XDebug.
note
Utilizzare il motore di ricerca preferito per imparare come configurare l'IDE. Si può
guardare alla configurazione di sf_file_link_format
o xdebug.file_link_format
,
entrambi funzionano nello stesso modo.
Fare i test più rapidamente
Registrare i test funzionali
I test funzionali simulano l'interazione dell'utente per valutare accuratamente l'integrazione di tutti i pezzi dell'applicazione. Scrivere i test funzionali è facile, ma richiede tempo. Ma siccome ogni file di test funzionale è uno scenario che simula un utente che naviga nel sito e siccome navigare una applicazione è più rapido che scrivere del codice PHP, l'ideale sarebbe registrare una sessione del browser e averla convertita automaticamente in codice PHP. Fortunatamente, symfony ha un tale plugin. Si chiama swFunctionalTestGenerationPlugin, e permette di generare in pochi minuti degli scheletri di test pronti per essere personalizzati. Naturalmente per renderlo utile, sarà comunque necessario aggiungere le chiamate al tester adeguato, ma questo è in ogni caso un notevole risparmio di tempo.
Il plugin lavora registrando un filtro di symfony, che intercetta tutte le
richieste e le converte in codice di test funzionali. Dopo aver installato
il plugin nel solito modo, bisogna abilitarlo. Aprire il file filters.yml
dell'applicazione e aggiungere le seguenti linee dopo la riga di commento:
functional_test:
class: swFilterFunctionalTest
Alla fine, attivare il plugin nella classe sfProjectConfiguration
:
// config/ProjectConfiguration.class.php class ProjectConfiguration extends sfProjectConfiguration { public function setup() { // ... $this->enablePlugin('swFunctionalTestGenerationPlugin'); } }
Siccome il plugin usa la barra degli strumenti web del debug come principale interfaccia utente, bisogna essere sicuri che sia abilitata (questo è il caso dell'ambiente di sviluppo, per impostazione predefinita). Appena abilitato, viene reso disponibile un nuovo menu chiamato "Functional Test". In questo pannello è possibile avviare la registrazione di una sessione, cliccando sul link "Activate" e ripristinare la sessione corrente cliccando su "Reset". Quando si ha finito, copiare e incollare il codice dalla textarea in un file dei test e iniziare a personalizzarlo.
Lanciare la suite di test più velocemente
Quando si ha una suite di test molto grande, può richiedere molto tempo lanciare
tutti i test ogni volta che si fanno delle modifiche, specialmente se alcuni
test falliscono. Questo perché ogni volta che si mette a posto un test bisognerebbe
rieseguire nuovamente l'intera suite di test per essere sicuri di non avere creato
dei malfunzionamenti da qualche altra parte. Ma finché i test che falliscono
non vengono messi a posto, non c'è altra possibilità che rieseguire tutti gli
altri test. Il task test:all
ha una opzione --only-failed
(-f
come
scorciatoia) che forza i task a rieseguire solo i test che sono falliti durante
l'esecuzione precedente:
$ php symfony test:all --only-failed
La prima volta, tutti i test vengono eseguiti come al solito. Ma per l'esecuzione dei successivi test, solo i test che sono falliti l'ultima volta verranno eseguiti. Nel momento in cui si mette a posto del codice, alcuni test passeranno e saranno rimossi dalle successive esecuzioni. Quando tutti i test passeranno nuovamente, verrà lanciata l'intera suite di test... si può allora ricominciare il ciclo e ripetere le varie fasi.
This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License license.