mercoledì 30 settembre 2009

symfony, creazione schema database (schema.yml)

A partire dalle specifiche iniziali dell'applicazione viste in precedenza, iniziamo a lavorare sul modello dati di Lyra.

Attivazione Doctrine

L'applicazione utilizzerà Doctrine come ORM quindi è necessario attivare il relativo plugin in config/ProjectConfiguration.class.php

public function setup()
{
  $this->enablePlugins(array('sfDoctrinePlugin'));
  $this->disablePlugins(array('sfPropelPlugin'));
}

Occorre poi pulire la cache di symfony con

./symfony cc

Poiché abbiamo abilitato un nuovo plugin bisogna utilizzare il comando plugin:publish-assets per consentire l'installazione di eventuali file accessori (immagini, css, javascript) necessari al funzionamento del plugin.

./symfony plugin:publish-assets

Infine è bene rimuovere ogni riferimento a Propel (l'ORM alternativo a Doctrine) che non sarà utilizzato.

rm web/sfPropelPlugin
rm config/propel.ini
rm config/schema.yml

Creazione dello schema del database

In symfony la struttura delle tabelle necessarie all'applicazione viene definita in un file in formato YAML (schema.yml). Per maggiori dettagli su questo formato si può consultare il sito ufficiale (http://yaml.org/).

Si tratta comunque di un formato abbastanza intuitivo e non difficile da utilizzare una volta visti alcuni esempi.

Il file schema.yml deve essere collocato in una cartella config/doctrine che va creata

mkdir config/doctrine

Le tabelle necessarie per questa versione preliminare di Lyra sono:

  • Tipi di contenuto
  • Articoli
  • Commenti
  • Cataloghi
  • Etichette

Non è possibile fare adesso un esame dettagliato del file schema.yml. La versione completa può essere scaricata da Google Code. Inoltre tutti i dettagli sulla struttura dei file sono disponibili sulla documentazione ufficiale di symfony.

config/doctrine/schema.yml
  
  LyraArticle:
    tableName: articles

LyraArticle è il nome della classe autogenerata da Doctrine che, come si vedrà, utilizzeremo per gestire i record della tabella articoli, articles è il nome della tabella sul database.

actAs:
    Timestampable: ~
    Sluggable:
      fields: [title]
      canUpdate: true
      unique: true
      indexName: article_slug

actAs indica una serie di comportamenti predefiniti del modello implementati da Doctrine senza che si debba scrivere codice.

Timestampable

Alla tabella verranno aggiunti due campi created_at, updated_at che saranno mantenuti automaticamente aggiornati con la data di creazione e di ultima modifica del record.

Sluggable

Alla tabella verrà aggiunto un campo slug con lo stesso contenuto del campo title modificato in questo modo:

  • gli spazi sono trasformati in '-';
  • i caratteri diversi da lettere e numeri sono rimossi;
  • i caratteri maiuscoli sono trasformati in minuscoli;
  • i caratteri accentati sono convertiti nell'equivalente non accentato.

Se ad esempio il campo title di un record contiene

Però che bell'articolo

il campo slug conterrà

pero-che-bell-articolo

In questo modo il campo slug può essere utilizzato per generare le URL SEF. canUpdate impostato a true consente la modifica da parte dell'utente del campo generato automaticamente, unique impostato a true indica che il campo deve essere univoco nella tabella: se due articoli hanno lo stesso identico titolo, sarà utilizzato un suffisso numerico progressivo nello slug per differenziarli. Con indexName indichiamo il nome da dare all'indice sul campo slug.

options:
    collate: utf8_unicode_ci
    charset: utf8

Impostiamo set di caratteri e collazione in utf-8.

columns:
    id:
      type: integer(4)
      primary: true
      autoincrement: true
    title:
      type: string(255)
      notnull: true
...

In columns definiamo i campi della tabella. Con primary e autoincrement a true indichiamo che il campo id sarà la chiave primaria autoincrementante della tabella, con type impostiamo il tipo del campo. Nello schema si utilizzano tipi indipendenti dal database utilizzato. Al momento della generazione degli script SQL per la creazione delle tabelle, sarà Doctrine a convertire questi tipi in quelli corrispondenti al particolare database scelto.

Ecco le corrispondenze tra i tipi di dato Doctrine utilizzati nello schema che stiamo esaminando e tipi MySQL:

DoctrineMySql
integer(1)tinyint
integer(4)int
booleantinyint(1)
cloblongtext
clob(65532)text
timestampdatetime

Per quanto riguarda i tipi di dato string, se la lunghezza è inferiore o uguale a 255 corripondono al tipo MySQL varchar della stessa lunghezza, se la lunghezza è superiore a 255 corrispondono a text, mediumtext o longtext.

Ometto i campi rimanenti della tabella Articoli e passo alla tabella Commenti soffermandomi però solo sulla parte più significativa.

LyraComment:
...

columns:
    id:
      type: integer(4)
      primary: true
      autoincrement: true
    article_id:
      type: integer(4)
...
relations:
    CommentArticle:
      class: LyraArticle
      local: article_id
      foreign: id
      foreignAlias: ArticleComments
      onDelete: CASCADE

Nello schema dobbiamo anche definire le relazioni tra tabelle, in questo caso la relazione uno a molti tra la tabella Articoli e la tabella Commenti:

  • class: nome della classe della tabella correlata (Articoli);
  • local: nome del campo di relazione nella tabella locale (Commenti);
  • foreign: nome del campo di relazione nella tabella correlata;
  • foreignAlias: nome della relazione vista 'dall'altro lato', cioè da quello della tabella Articoli. Vedremo in seguito a cosa serve;
  • onDelete: impostato su CASCADE determina la cancellazione automatica dei commenti quando il record correlato in Articoli viene cancellato.

Nella parte restante del file schema.yml si trova anche un esempio di come definire una relazione molti a molti, quella tra gli Articoli e le Etichette.

Vedremo la prossima volta come a partire dallo schema saranno generate le classi del Modello e gli script SQL per la creazione delle tabelle.

Ho eseguito il commit della revisione 5 su Google Code.

martedì 29 settembre 2009

symfony, creazione progetto e applicazione

In simfony un progetto è suddiviso in una o più applicazioni. È abbastanza comune avere almeno un'applicazione per il frontend e un'applicazione per il backend ed è così che sarà strutturato Lyra. Procediamo con ordine e creiamo per prima cosa il progetto. Da terminale e posizionati nella cartella radice del progetto (che, ripeto, nel mio caso è ~/sfprojects/lyra) digitiamo il comando

php lib/vendor/symfony/data/bin/symfony generate:project lyra

Il risultato sarà la creazione di un bel numero di cartelle che si aggiungono alla cartella lib che abbiamo creato la volta scorsa e che contiene il framework. L'albero delle cartelle del progetto è ora il seguente (riporto solo il primo livello, alcune cartelle contengono ulteriori sotto cartelle)

~
  sfprojects
    lyra
      apps
      cache
      config
      data
      doc
      lib
      log
      plugins
      test
      web

Tra i vari file creati dal comando generate:project, nella cartella radice del progetto ce n'è uno chiamato symfony che ci permetterà da ora in poi di eseguire i comandi senza specificare il percorso completo (lib/vendor/symfony/data/bin/symfony).

In Linux ad esempio basterà digitare dalla cartella radice del progetto

./symfony comando opzioni argomenti

Con il comando generate:app creiamo l'applicazione di frontend per il nostro progetto

./symfony generate:app --escaping-strategy=on --csrf-secret=gfhtyy87 frontend

Dei due parametri escaping-strategy e csrf-secret (a quest'ultimo si passa una sequenza di caratteri scelta a caso) ci sarà modo di parlare in seguito, per ora dico solo che è opportuno specificarli perché impostano strategie predefinite importanti per la sicurezza dell'applicazione.

Per effetto di questo comando una serie di cartelle sono create all'interno della cartella apps

~
  sfprojects
    lyra
      apps
        frontend
          config
          i18n
          lib
          modules
          templates
...

Prima di proseguire è bene fare subito una modifica al file di configurazione del progetto per renderlo facilmente rilocabile da un server ad un altro. All'inizio di config/ProjectConfiguration.class.php troviamo questa riga

require_once '/home/gmassi/sfprojects/lyra/lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php';

Ovviamente chi ha eseguito le varie operazioni sul proprio server di sviluppo avrà il percorso alla propria cartella. Modificare la riga così:

require_once dirname(__FILE__).'/../lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php';

Arrivati a questo punto siamo quasi in grado di visualizzare qualcosa nel browser. Prima però è necessario configurare un host virtuale per il progetto. Ecco la procedura da seguire (Linux Ubuntu).

sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/lyra
sudo gedit /etc/apache2/sites-available/lyra

Modificare il file di configurazione in questo modo (ovviamente con i propri percorsi al posto di '/home/gmassi/...')

<VirtualHost *:80>
  ServerAdmin webmaster@localhost
  ServerName lyra
  DocumentRoot /home/gmassi/sfprojects/lyra/web
  <Directory />
    Options FollowSymLinks
    AllowOverride None
  </Directory>
  <Directory /home/gmassi/sfprojects/lyra/web>
    AllowOverride All
    Allow from All
  </Directory>

  Alias /sf /home/gmassi/sfprojects/lyra/lib/vendor/symfony/data/web/sf
  <Directory "/home/gmassi/sfprojects/lyra/lib/vendor/symfony/data/web/sf">
    AllowOverride All
    Allow from All
  </Directory>
</VirtualHost>

Abilitare l'host virtuale con

sudo a2ensite lyra
sudo /etc/init.d/apache2 restart

Per finire,

sudo gedit /etc/hosts

e aggiungere l'host virtuale appena creato sulla prima riga dopo localhost

127.0.0.1 localhost lyra

Possiamo lanciare il browser e scrivere nella barra degli indirizzi

http://lyra/index.php/

Se abbiamo mod_rewrite abilitato sul server di sviluppo (consigliabile) va bene anche semplicemente

http://lyra/

Se tutti i passaggi sono stati seguiti correttamente comparirà la pagina di benvenuto predefinita di simfony.

Ho eseguito il commit della revisione 4 su Google Code. A questo punto per crearsi localmente il proprio ambiente di sviluppo si hanno due possibilità:

1) Si eseguono in sequenza le operazioni descritte nell'articolo precedente (Installazione del framework) ed in questo.

2) Ci si limita a creare una propria cartella locale per il progetto ad esempio ~/sfprojects/lyra e da una finestra terminale si esegue il checkout della revisione 4. Chiaramente il client Subversion deve essere installato.

cd ~/sfprojects/lyra
svn checkout -r4 http://lyra-cms.googlecode.com/svn/trunk/ .

Poi si assegnano i permessi alle cartelle cache e log

chmod 777 cache
chmod 777 log

Infine si seguono le indicazioni presenti in questo articolo per creare un host virtuale che abbia come Document Root la cartella web all'interno della propria cartella del progetto.

Dalla prossima volta si inizierà lo sviluppo del modello dati specifico per la nostra applicazione.

lunedì 28 settembre 2009

Installazione del framework symfony

È il momento di iniziare lo sviluppo di Lyra. Come ho già detto detto utilizzerò Linux Ubuntu come server di sviluppo. Comunque la documentazione ufficiale (a partire dal già citato Getting started with symfony) riporta le istruzioni necessarie a configurare ed utilizzare symfony anche sotto Windows.

La prima cosa da fare è creare una cartella per il progetto, io ho scelto di crearla all'interno di una cartella sfprojects nella mia 'home'. Essendo gmassi il mio mome utente su Ubuntu il percorso completo è

/home/gmassi/sfprojects/lyra

All'interno di questa cartella ne va creata un'altra lib e al suo interno un'altra ancora vendor

/
  home
    gmassi
      sfprojects
        lyra
          lib
            vendor

A questo punto possiamo installare il framework. Dalla pagina di download scarichiamo il pacchetto con l'ultima versione disponibile di symfony (symfony-1.2.8.tgz) e lo decomprimiamo nella cartella vendor. La decompressione dell'archivio genera una cartella symfony-1.2.8 che deve essere rinominata in symfony.

Il risultato finale dell'operazione deve essere questo:

/
  home
    gmassi
      sfprojects
        lyra
          lib
            vendor
              symfony
                data
                docs
                lib
                licenses
                test

Mostro solo il primo livello sotto la cartella symfony, ma ci sono ovviamente altre sottocartelle. Per verificare che l'installazione del framework sia andata bene posizioniamoci nella cartella del progetto digitando in una finestra terminale

cd ~/sfprojects/lyra

A beneficio dei meno esperti di Linux ricordo che ~ (tilde) indica la cartella 'home' dell'utente corrente (nel mio caso /home/gmassi). Quindi verifichiamo il numero di versione di symfony con il comando

php lib/vendor/symfony/data/bin/symfony -V

Come ho già accennato precedentemente, già da qui si può notare che symfony richiede di poter eseguire script PHP da linea di comando almeno sul server di sviluppo.

A questo punto eseguo il commit delle modifiche su Google Code. Siamo alla revisione 3

Alla fine di ogni articolo scriverò sempre il numero di revisione corrente. Ogni client Subversion consente di estrarre dal repository con un'operazione di checkout o update lo stato dell'applicazione aggiornato ad un determinato numero di revisione. In questo modo non solo si avrà sempre a disposizione la versione più recente dell'applicazione, ma si potranno ricostruire tutte le fasi dello sviluppo attraverso le diverse revisioni.

Ad esempio se, come ho fatto io, si è creata la cartella del progetto come sfprojects/lyra nella propria 'home', e si è installato il client Subversion, per scaricare da Google Code l'applicazione al punto esatto dello sviluppo a cui siamo arrivati con questo articolo si possono utilizzare queste istruzioni da terminale

cd ~/sfprojects/lyra
svn checkout -r3 http://lyra-cms.googlecode.com/svn/trunk/ .

Attenzione al punto al termine della seconda riga, è importante metterlo. Se si omette l'opzione -r si scaricherà la versione più recente dell'applicazione.

venerdì 25 settembre 2009

Realizzare un cms con symfony

Come promesso la volta scorsa vediamo qualche dettaglio sull'applicazione che svilupperemo con symfony. Trattandosi di un framework è evidente che symfony consente la realizzazione di qualsiasi tipo di applicazione, io per questa serie di articoli ho scelto di sviluppare un semplice (ma espandibile) gestore di contenuti.

Con tutte le piattaforme blog e i cms disponibili si potrebbe chiedere che senso abbia svilupparne uno con un framework. Mi vengono in mente alcune possibili riposte, elencate in ordine di importanza:

  • Perché può essere divertente farlo;
  • Perché mentre lo si fa si rischia di imparare qualcosa;
  • Perché si ha l'opportunità di costruirsi un prodotto su misura per le proprie esigenze.

Le funzionalità iniziali del cms saranno le seguenti, di sicuro mi dimentico qualcosa:

  • Gestione di più tipologie di contenuto;
  • inserimento contenuti da backend e frontend anche con editor WYSIWYG;
  • catalogazione dei contenuti in categorie, sottocategorie nidificate in più livelli;
  • "alberi" di categorie diversi a seconda del tipo di contenuto;
  • gestione dei commenti;
  • gestione feed;
  • URL semplificate o URL SEF come si preferisce chiamarle.

Ecco almeno a grandi linee come si procederà. Dopo la creazione della struttura del database e l'inserimento di alcuni dati iniziali si inizierà lo sviluppo del frontend: visualizzazione articoli in prima pagina (con sommario e link 'leggi tutto'), visualizzazione articolo a pagina intera, creazione e modifica articoli, inserimento commenti, visualizzazione articoli per categoria.

Si passerà poi al backend: gestione categorie, che si chiameranno etichette e saranno suddivise in cataloghi, gestione articoli e commenti (approvazione, modifica, cancellazione), a seguire una iniziale gestione utenti.

Il primo traguardo è arrivare ad un'applicazione in grado di gestire un blog personale o comunque un sito in cui la gestione dei contenuti sia centralizzata nelle mani dell'amministratore. Inizialmente sarà disponibile un solo tipo di contenuto (articolo) e il tutto sarà abbastanza spartano. Da lì si partirà per perfezionare le funzioni esistenti, migliorare la gestione utenti e sviluppare la gestione di ulteriori tipi di contenuto.

Serve a questo punto dare un nome all'applicazione, mi è piaciuto Lyra, scegliere una licenza, la mia preferita è la GNU/GPL (versione 2) e infine predisporre un repository per il codice perché sarebbe impossibile allegare i listati nel blog. A questo scopo ho scelto Google Code. L'uso di un repository Subversion permette tra l'altro di avere sempre a disposizione i vari stadi dello sviluppo dell'applicazione (attraverso le diverse revisioni) e quindi di seguire meglio il filo del discorso.

Dalla prossima volta inizieremo in concreto lo sviluppo.

mercoledì 23 settembre 2009

Introduzione a symfony

Prima di iniziare lo sviluppo con symfony dell'applicazione di esempio cui ho accennato la volta scorsa, penso siano utili alcune considerazioni preliminari.

L'applicazione sarà sviluppata con symfony 1.2.8. L'installazione include due plugin alternativi (Propel e Doctrine) con funzioni di ORM (Object Relational Mapper) che mettono a disposizione un'interfaccia ad oggetti per creare ed eseguire query SQL e compiere tutte le operazioni sul database. Sarà utilizzato Doctrine.

Requisiti

La versione del framework che utilizzeremo richiede PHP in versione 5.2.4 o superiore. Sono poi necessari un web server ed un server di database. Io utilizzerò Apache 2.2 e MySql 5.0.

PHP dovrà essere configurato per eseguire script anche da linea di comando non solo tramite web server in quanto durante lo sviluppo symfony richiede l'esecuzione di diverse istruzioni da linea di comando.

Ambiente di sviluppo

Naturalmente è opportuno realizzare l'applicazione su un server di sviluppo locale per poi trasferirla sul server online. Io utilizzerò un normalissimo Linux Ubuntu 9.0.4.

A chi dovesse installare da zero l'ambiente di sviluppo locale, consiglierei:

Per Windows

Installare Wamp o Xampp per Windows.

Per Linux

1) Installare le varie componenti separatamente

Queste guide sono per Ubuntu, se necessario guide specifiche per diverse distribuzioni di Linux si trovano facilmente su Google.

2) Alternativamente installare Xampp per Linux

Entreremo nei dettagli dell'applicazione la prossima volta.

Nel frattempo a chi non abbia grande familiarità con il framework, ma volesse comunque seguire gli articoli, consiglierei di leggere almeno la guida Getting started with symfony (in italiano).

martedì 22 settembre 2009

Programma per l'autunno

Come si può notare dall'archivio non ho avuto molto tempo di scrivere sul blog ultimamente, ma con l'arrivo dell'Autunno mi propongo di aumentare la frequenza degli articoli. Gli argomenti saranno in parte diversi da quelli trattati fino ad ora, un po' perché mi piace cambiare un po' perché scrivo sul blog prevalentemente di quello di cui mi occupo al momento.

In particolare ho in programma una serie di brevi articoli su symfony, un framework PHP basato sul design pattern Model View Controller di cui ho avuto modo di approfondire la conoscenza negli ultimi mesi.

Vorrei provare a realizzare una guida pratica 'a puntate' sviluppando con symfony, pezzo per pezzo, un'applicazione reale, inizialmente molto semplice, ma che possa essere migliorata e arricchita di funzionalità nel tempo. Magari grazie anche ai suggerimenti e, perché no, al codice di qualche lettore interessato a contribuire.

L'idea, lo dico subito, non è del tutto originale in quanto il più conosciuto dei tutorial di simfony (Jobeet) è costituito da una serie di articoli inizialmente pubblicati sul blog ufficiale, attraverso i quali viene sviluppata una applicazione completa.

Oltre ovviamente ad utilizzare una diversa applicazione di esempio, vorrei non pormi limiti di tempo e portare avanti lo sviluppo fino a che sarà divertente ed interessante farlo. L'intenzione non è certo quella di duplicare la documentazione del framework che è esauriente e disponibile anche in italiano, ma piuttosto quella di fornire qualche esempio pratico di codice. Maggiori dettagli prossimamente.

Naturalmente se ce ne sarà l'occasione scriverò di ancora di Joomla, Drupal, Javascript, PHP ma con minore frequenza rispetto al passato.