Documento Allegato

Transcript

Documento Allegato
Dlibs/DSite 1.0
prima bozza di documentazione
Autore: LM
Revisione: 0.3
Contenuti del documento
DLibs....................................................................................................................................................3
Introduzione.....................................................................................................................................3
Struttura delle directory...................................................................................................................3
ActiveDB....................................................................................................................................3
ActiveForm.................................................................................................................................3
DataSource..................................................................................................................................4
Externals......................................................................................................................................4
General........................................................................................................................................4
ActiveDB ........................................................................................................................................5
Convenzioni................................................................................................................................5
Utilizzo di base............................................................................................................................6
I metodi di ricerca.......................................................................................................................7
Metodi get a disposizione.......................................................................................................7
Metodi find a disposizione.....................................................................................................8
Rules............................................................................................................................................8
Rule con parametri......................................................................................................................9
Gli inserimenti/modifiche/cancellazioni...................................................................................10
Le relazioni master/detail..........................................................................................................11
Come uscire dallo schema delle convenzioni...........................................................................11
I callback...................................................................................................................................11
I metodi avanzati.......................................................................................................................11
Dsite....................................................................................................................................................12
Struttura delle directory.................................................................................................................12
cache..........................................................................................................................................12
config........................................................................................................................................12
libs.............................................................................................................................................12
website......................................................................................................................................13
amp.......................................................................................................................................13
controllers.............................................................................................................................13
files.......................................................................................................................................13
js, pics, styles........................................................................................................................13
logs.......................................................................................................................................13
models..................................................................................................................................13
plugin-config........................................................................................................................13
variables................................................................................................................................13
views.....................................................................................................................................13
urlmap.php............................................................................................................................14
index.php..............................................................................................................................14
Il primo test....................................................................................................................................14
Multilingua.....................................................................................................................................16
Variabili di default.........................................................................................................................16
Modelli e templates........................................................................................................................16
Controllers.....................................................................................................................................16
ImageServer...................................................................................................................................16
Urlmap...........................................................................................................................................16
DLibs
Introduzione
Dlibs è un framework di librerie PHP nato per velocizzare le comuni operazioni svolte
durante lo sviluppo di una applicazione o di un sito web. Il framework è scritto in PHP5 ed
è incompatibile con PHP4. Tutti gli include utilizzati nelle Dlibs assumono che la root
directory delle librerie sia nell'include path. L'include path può essere settato sia nel file
php.ini sia runtime, tramite la funzione set_include_path().
Struttura delle directory
In tutte le directory di trova una directory "test". La directory test contiene gli unit-test della
sezione delle dlibs corrispondente ed è invocabile direttamente da browser. (C'è un
index.php che si occupa di lanciare i test)
ActiveDB
Contiene ActiveDB e le classi derivate. ActiveDB è un'implementazione che si basa (ma
non segue al 100%) il pattern ActiveRecord. Lo scopo di ActiveDB è quello di fornire
un'astrazione per la base dati, su cui basare le proprie operazioni di ricerca, inserimento,
cancellazione e modifica dei record.
La classe AcriveDB fornisce quindi un'astrazione relativa ad una tabella del database.
Le princilapli classi derivate da ActiveDB sono ActiveQuery, che consente di utilizzare le
funzioni ricerca su una query custom, invece che su una tabella, e DContentActiveDB (e
MLDcontentActiveDB) che permettono di utilizzare i metodi di ActiveDB su tabelle che
abbiano una gestione del Workflow (vedremo in seguito).
La classi che finiscono per "DbWrapper" costituiscono i "Drivers" di accesso al Database.
Al momento sono disponibili solo MySQLDbWrapper per i database MySQL e
ODBCDbWrapper per le fonti dati ODBC (utilizzabile solo in ambiente Windows). Le classi
DbWrapper Debbono implementare l'interfaccia AbstractDB per potere essere utilizzate da
ActiveDB.
Tutte le altre classi sono classi di appoggio, che vedremo nella descrizione dettagliata.
ActiveForm
ActiveForm è un insieme di classi utilizzato per generare delle form in XHTML. ActiveForm
si occupa della generazione dei componenti, dei check di obbligatorietà dei dati, della
gestione degli errori e del display dell'XHTML delle form. Non gestisce, in nessun modo, il
tag <form> ne il tag <submit>. La parte di gestione che esula dalla generazione del codice
XHTML dei componenti e dai check di obbligatorietà dei dati viene lasciata allo
sviluppatore.
La directory components contiene i singoli componenti della form. Nel modello di
ActiveForm ogni singolo componente è rappresentato da una classe che estende la classe
base ActiveFormComponent. Ogni singolo componente è responsabile dei propri check di
esistenza o consistenza del dato e dell'output del proprio XHTML.
La classe DBFormGenerator è un Helper per generare delle istanze di ActiveForm
partendo da un oggetto ActiveDB.
DataSource
Contiene la classe DataSource, deprecata, che verrà presto rimossa dalle Dlibs.
Externals
Contiene le classi necessarie al funzionamento o al testing delle Dlibs, non sviluppate
all'interno del progetto. Al momento solo la classe simpletest, utilizzata per lo unit-testing.
La classe simpletest non è necessaria al funzionamento delle Dlibs e può quindi essere
eliminata dall'ambiente di produzione.
General
General contiene una collezione di classi generiche d'appoggio.
CalendarManager: permette di costruire cicli su giorni, settimane, mesi, di individuare,
dato un giorno, la settimana e il mese corrispondente o il primo o l'ultimo giorno della
settimana o del mese corrispondente. Molto utile per la costruzione di calendari.
DirWalker: classe statica per listare il contenuto di una directory, filtrando il contenuto per
estensione. (La classe DirWalker2 è in fase di ricostruzione o eliminazione, da non usare)
DLString: classe utilizzata per trasformare una stringa in una semplificzione utile per gli
indici di ricerca. Permette la "romanizzazione" (trasformazione di tutti i caratteri speciali,
accentati o simili nell'equivalente "romano"), l'appiattimento delle doppie ( Mazza in Maza
ad esempio). La classe utilizza le funzioni di PHP per la manipolazione delle stringhe
multibyte.
IncludeManager: classe utilizzata per costruire una tabella di file da includere (css,
javascript o similari) utilizzati dalle DLibs. Utilizzata praticamente solo da ActiveForm,
risulta un po' ostica nei suoi meccanismi. Non è esclusa una persante revisione.
Logger: sistema di log dei messaggi. E' costituita da una classe principale e da una serie
di Writer. Un writer è una classe che permette di scrivere un messaggio di log su un
particolare supporto. Sono disponibili, ad esempio, FileWriter, per scrivere su file,
MailWriter, per inviare la riga di log via mail (utile per loggare gli errori importanti) e
ActiveDBWriter per salvare su una tabella di database.
SimpleObject: è di fatto la classe di base per ActiveDB e per alcune classi di DSite. Il suo
compito principale è quello di mappare le sue proprietà su un array associativo e di
permettere un completo controllo di getter/setter per tutte le classi che ne derivano.
Implementa le interfacce PHP ArrayAccess e Iterator, permettendo così di scorrere le
proprietà di un oggetto sia tramite il normale operatore di accesso -> che tramite
[proprietà] come se si trattasse di un array, sia tramite un ciclo foreach.
Singleton: semplice classe statica che permette di utilizzare il pattern singleton con
qualsiasi altra classe.
UrlMapper: classe che permette di registrare delle mappe di url nel formato
/{variabile1}/test_{variabile2} e di eseguire il match di una stringa (URL) con le mappe
registrate, ottenendo in caso di match positivo, la lista di variabili espresse nella mappa
(coppie associative chiave=>valore)
ImageManager: lo sviluppo di questa classe non è ancora ultimato. Si tratta di un porting
nelle dlibs dell'omonimo plugin per DSite. Attualmente non è utilizzabile.
Workflow: gestore di workflow, compatibile con i files XML del vecchio sistema DContent
(CMS proprietario di DSign). Permette l'utilizzo di un workflow espresso tramite un file
XML. Utilizzato da DContentActiveDB, ma abbastanza generico per essere utilizzato
anche separatamente.
ActiveDB
Si può dire che ActiveDB sia di fatto la parte più importante delle Dlibs, o quantomeno la
più utilizata. Svolge quasi tutte le operazioni di lettura, scrittura, cancellazioni necessarie
per l'utilizzo di un DB in una web-application.
Convenzioni
Un oggetto ActiveDB rappresenta sempre (o almeno, così dovrebbe essere), una tabella
di un Database relazionale. Nelle Dlibs si predilige un approggio "Convention over
Configuration" ovvero se non specificato altrimenti il sistema si basa su convenzioni
interne, che possono però essere alterate facilmente. In questo modo se si progetta un
sistema per funzionare con le Dlibs, seguendo le convenzioni, basteranno pochissime
righe di codice per potere utilizzare ActiveDB. Se ci si deve adattare a strutture già
esistenti questo non è un problema, sarà necessario però scrivere più codice, per
specificare la struttura delle tabelle su cui andremo a lavorare.
Le convenzioni usate da ActiveDB sono:
1. Ogni tabella ha sempre una Primary Key
2. La chiave primaria di una tabelle si chiama sempre <NomeTabella>KEY ed è un
campo numerico con autoincrement. Quindi se la tabella si chiama "Pagine" la sua
chiave primaria sarà "PagineKEY".
3. Le Foreign Key si chiamano <NomeTabellaPadre>FKEY, e sono ovviamente
numeriche. Dunque se abbiamo una tabella Immagini collegata in relazione 0-n con
la tabella Pagine (Pagine è "0" il master, Immagini è "n" il detail) la chiave primaria
di Immagini sarà ImmaginiKEY e la chiave che punta a Pagine sarà PagineFKEY
4. La classe ActiveDB che gestisce una tabella si chiama sempre come la tabella
stessa.
Utilizzo di base
Per potere utilizzare ActiveDB su una tabella è per prima cosa necessario definire la
classe che si occupa della gestione della tabella. Bisogna sempre, assolutamente
rispettare il rapporto una classe, una tabella. Prendiamo come esempio la tabella Pagine,
così strutturata:
PagineKEY:
Codice:
Titolo:
Abstract:
Corpo:
Thumbnail:
Ordine:
chiave primaria
varchar(255)
varchar(255)
varchr(255)
Text
varchar(255)
tinyint
Per definire la classe che la gestisce:
class Pagine extends ActiveDB {}
A questo punto la classe di gestione della tabella Pagine è pronta. Ora basta istanziarla.
Per farlo abbiamo bisogno di collegrci al Database. Lo faremo con un MySQLDbWrapper.
// host,dbname, username, password
$dbw=new MySQLDbWrapper("localhost","test","username","password");
$pgn=new Pagine($dbw);
Ora $pgn rappresenta la tabella pagine. Se per esempio vogliamo stampare i titoli di tutte
le pagine contenute nella tabella possiamo fare:
foreach($pgn->getAll() as $pagina)
print($pagina->Titolo."<br/>");
Come si vede dall'esempio tutti i field della tabella sono stati mappati sulle proprietà
corrispondenti dell'oggetto $pagina. Possiamo quindi avere accesso a:
$pagina->Titolo, $pagina->Abstract, $pagina->Corpo e così via.
Per accedere alla primary key della tabella si può invece usare la scorciatoia
$pagina->PrimaryKEY
che nel nostro caso di esempio equivale a
$pagina->PagineKEY
Attenzione: il nome delle proprietà è case sensitive.
Continuando a usare la funzione getAll() possiamo ad esempio volere ottenere la stessa
lista, ma ordinata er il campo "Ordine".
$pgn->getAll(array(OrderBy => "Ordine"));
Il primo parametro di getAll è un array associativo di proprietà che permettono di
modificare la "select" che viene fatta per estrarre i dati. In particolare per ora possiamo
utilizzare "Where" per aggiungere (in and) una clausola where alla select e OrderBy per
specificare l'ordinamento. Il metodo getAll restituisce un array di oggetti ActiveDB, che
rappresentano il risultato della ricerca.
I metodi di ricerca
ActiveDB mette a disposizione vari metodi di ricerca, che possiamo dividere in 2
macrocategorie: i metodi "get" e i metodi"find".
La differenza tra le due categorie è che i metodi "get" restituiscono sempre un array di
oggetti o un singolo oggetto. Se facciamo quindi con un metodo getAll una get di una
tabella con 10.000 record ci troveremo con un array di 10.000 oggetti ActiveDB ed un
conseguente dispendio di memoria e tempo. I metodi "find" invece preparano la query di
ricerca ma lasciano allo sviluppatore l'onere del ciclo per estrarre i dati.
Per chiarire la differenza, se seguenti due porzioni di codice ottengono lo stesso risultato:
// utilizzando un metodo get
$dbw=new MySQLDbWrapper("localhost","test","username","password");
$pgn=new Pagine($dbw);
$dat=$pgn->getAll();
// utilizzando un metodo find
$dbw=new MySQLDbWrapper("localhost","test","username","password");
$pgn=new Pagine($dbw);
$pgn->findAll();
while($dt=$pgn->fetchObject())
$dat[]=$dt;
Metodi get a disposizione
(il parametro $params è sempre un array associativo che può contenere le chiavi Where e
OrderBy)
- getAll($params)
get di tutti i record che corrispondono ai parametri in $params
- getBlock($start, $end, $parameters)
get dei record dall'offset $start a $end che corrispondono ai parametri in $params
- getPage($pagenum, $pagelen, $params)
get dei record della pagina $pagenum che corrispondono ai parametri in $params. il
parametro $pagelen esprime la lunghezza, in record, della pagina. Il valore di default è 10.
- getHalf($pos, $params)
get della metà dell'intero set di record (espressa da $pos. 1= prima metà, 2 = seconda
metà) corrispondente ai parametri in $params.
- getObject($params)
get di un singolo oggetto (il primo in caso di più risultati), risultante dalla ricerca
corrispondente ai parametri in $params
- getAllBy_{nomecampo}($value)
get di tuttii record in cui il campo {nomecampo} è uguale al parametro dato. Prendendo ad
esempio la tabella Pagine citata sopra possiamo scrivere
$pgn->getAllBy_Codice("home")
Questo equivale ai risultati della query
Select * From Pagine Where Codice='home'
- getAllLike_{nomecampo}($value)
Come il metodo precedente, solo che utilizza Like al posto di "=". Scrivendo quindi
$pgn->getAllLike_Titolo("News%")
si otterrà il risultato della query
Select * From Pagine Where Titolo like 'News%'
- getBlockBy_{nomecampo}($start,$end,$value)
- getPageBy_{nomecampo}($pagenum,$pagelen,$value)
- getHalfBy_{nomecampo}($pos,$value)
- getObjectBy_{nomecampo}($value)
Sono quindi tutti equivalenti dei metodi corrispondenti sopracitati, che però utilizzano il
metodo di generazione della where visto per getAllBy_{nomecampo}($value)
Metodi find a disposizione
I metodi find sono in realtà molto simili, nella loro interfaccia e funzionamento, ai
metodi get precedentemente visti. L'unica grande differenza, come già accennato, è
che il fetch dei dati viene lasciato allo sviluppatore. I parametri $param sono
sostanzialmente identicia quelli dei metodi get
findAll($params)
Prepara la query per il fetch di tutti i record corrispondenti ai parametri in $params
findAllBy_{nomecampo}($value)
Prepara la query per il fetch di tutti i record corrispondenti alla clausola
“nomecampo='$value'”
Rules
Per semplificare i modelli dati e rendere il codice più gestibile e manutenibile è stato creato
il concetto di “rule”. Una rule è di fatto una regola, tale e quale a quelle specificate tramite i
parametri $params visti in precedenza, che può essere associata ad un identificativo e
richiamata velocemente in un momento successivo. Per creare una rule si usa il metodo:
$adbobject->addRule($rulename,$params);
dove $adbobject è un oggetto derivato da ActiveDB, $rulename è l'identificativo univoco
della rule e $params è un array associativo di parametri (Where, OrderBy).
E' possibile specificare quindi una rule in questo modo:
class Pagine extends ActiveDB {}
$dbw=new MySQLDbWrapper("localhost","test","username","password");
$pgn=new Pagine($dbw);
$pgn->addRule(“homepages”,
array(Where => “Codice like 'home_%'”,
OrderBy => “Ordine”));
In questo modo abbiamo creato una rule chiamata homepages che corrisponderà alla
query:
Select * From Pagine Where Codice like 'home_%' Order By Ordine
In generale è però prassi apprezzata creare le rule direttamente nel costruttore della
classe ActiveDB. Questo rende il codice più leggibile e evita duplicazioni dovute alla
distrazione. In questo caso possiamo anche scrivere:
class Pagine extends ActiveDB {
public function __construct($dbw) {
parent::__construct($dbw);
$this->addRule(“homepages”,
array(Where => “Codice like 'home_%'”,
OrderBy => “Ordine”));
}
}
Così abbiamo ottenuto lo stesso effetto, però la rule sarà disponibile in ogni istanza della
classe.
Per potere utilizzare le rule appena create possiamo usare appositi metodi get o find:
getAll_{rulename}()
getObject_{rulename}()
getBlock_{rulename}($start, $end)
getPage_{rulename}($pagenum, $pagelen)
Questi metodi si comportano come i corrispondenti metodi get e find precedentemente
citati, ad esclusione del fatto che {rulename} specifica il nome della rule da applicare.
Sarà quindi possibile scrivere, dato $pgn un oggetto di tipo Pagine:
$homes=$pgn->getAll_homepages();
Rule con parametri
Spesso ovviamente una rule non basta in tutte le situazioni. Ad esempio se vogliamo
estrarre un set di record la cui data sia compresa tra due estremi. In questo caso saremmo
costretti a usare una normale getAll() con un parametro “Where”.
In questo caso ci vengono in aiuto le Rule con parametri. Prendiamo la tabella News così
definita:
NewsKEY:
DataNews:
Titolo:
Abstract:
Corpo:
Thumbnail:
chiave primaria
Date
varchar(255)
varchr(255)
Text
varchar(255)
Definiamo poi il modello per gestirla:
class News extends ActiveDB {
public function __construct($dbw) {
parent::__construct($dbw);
$this->addRule(“NewsInIntervallo”,
array( Where =>
}
}
“DataNews between '%1' and '%2'” ));
I placeholder %1 e %2 rappresentano i parametri della funzione get per utilizzare la rule.
Questo significa che ora possiamo usare, ad esempio:
$nws_lst=$nws->getAll_NewsInIntervallo(“2008-01-01”,”2008-12-31”);
dove ovviamente news è un'istanza di una classe vista sopra.
In caso di funzioni come getPage_ o getBlock_ che hanno alcuni parametri, i parametri
della Rule vanno in coda. Ad esempio:
$nws_lst=$nws->getBlock_NewsInIntervallo(1,10,“2008-01-01”,”2008-12-31”);
ci restituirà un array delle news dalla 1 alla 10 con DataNews nel 2008. In questo caso non
abbiamo specificato l'ordine in cui le news devono essere restituite. Possiamo ovviamente
parametrizzare anche il campo ordine, nello stesso modo. Ad esempio potremmo volere le
news in ordine ASC o DESC a seconda della lista che presentiamo nel sito. Facciamo una
piccola modifica alla nostra classe:
class News extends ActiveDB {
public function __construct($dbw) {
parent::__construct($dbw);
$this->addRule(“NewsInIntervallo”,
array( Where =>
“DataNews between '%1' and '%2'”,
OrderBy =>
“DataNews %3” ));
}
e quindi
$nws_lst=$nws->getAll_NewsInIntervallo(“2008-01-01”,”2008-12-31”,”DESC”);
Gli inserimenti/modifiche/cancellazioni
Appurato come gestire le ricerche con ActiveDB passiamo agli inserimenti, modifiche,
cancellazioni. Prendiamo come esempio la classe News vista nel capitolo precendente.
Istanziamola con:
$dbw=new MySQLDbWrapper("localhost","test","username","password");
$nws=new News($dbw);
Ora supponiamo di volere inserire una nuova news nella tabella:
$nws->DataNews=”2008-01-01”;
$nws->Titolo=”Plug è un mostro”;
$nws->Abstract=”Plug e Giovanni di nitrostudio.it sono delle belve”;
$nws->Corpo=”Lorem Ipsum etc etc Dolor etc Ipsum etc\n”.
”Lorem Ipsum etc etc Dolor etc Ipsum etc\n”.
”Lorem Ipsum etc etc Dolor etc Ipsum etc\n”;
$nes->save();
In questo modo abbiamo eseguito una insert sul database. Al termine del'operazione la
proprietà PrimaryKEY dell'oggetto $new viene settata sull'indice appena ottenuto dalla
insert.
Il metodo save si cura di eseguire l'operazione di insert oppure update a seconda della
presenza o meno della PrimaryKEY dell'oggetto. Se un oggetto ha una primary key settata
ad un valore il metodo save esegue una update, se la primary key non è settata allora
viene eseguita una insert. Se vogliamo cercare un record e modificarlo sarà quindi
possibile in questo modo:
$nws_nitro=$nws->getObjectBy_ Titolo(“Plug è un mostro”);
$nws_nitro->Titolo=”Plug e Giovanni sono delle belve”;
$nws_nitro->save();
Questo produrrà una Update che cambia di fatto il titolo della news trovata.
In alcuni casi è necessario utilizzare delle funzioni del DB per determinare il valore da
inserire, come ad esempio NOW() su mysql per ottenere la data odierna. Anteponendo e
postponendo “_” alla proprietà è possibile specificare al posto di un valore generico una
funzione. Rivediamo il codice di prima:
$nws->_DataNews_=”NOW()”;
$nws->Titolo=”Plug è un mostro”;
$nws->Abstract=”Plug e Giovanni di nitrostudio.it sono delle belve”;
$nws->Corpo=”Lorem Ipsum etc etc Dolor etc Ipsum etc\n”.
”Lorem Ipsum etc etc Dolor etc Ipsum etc\n”.
”Lorem Ipsum etc etc Dolor etc Ipsum etc\n”;
Come vedete DataNews è diventato _DataNews_, questo fa si che il valore “NOW()”
invece che essere interpretato come stringa venga gestito come funzione (nel nostro caso
di mysql).
La cancellazione di un record funziona sostanzialmente secondo gli stessi principi. Prima
si cerca un record, con effetto quindi di settare la PrimaryKEY, poi si usa il metodo
delete(). Prendiamo come esempio la nostra news iniziale:
$nws_nitro=$nws->getObjectBy_ Titolo(“Plug è un mostro”);
$nws_nitro->delete();
In questo modo avremo cancellato la news sulla belvalità di nitrostudio.
Le operazioni di update e delete si basano sempre sulla presenza di un valore nella chiave
primaria della tabella. Per questo motivo le tabelle, per potere essere utilizzate con
ActiveDB, devono sempre avere una chiave primaria.
Le relazioni master/detail
Come uscire dallo schema delle convenzioni
I callback
I metodi avanzati
basewhere
reset
resetfields
addfielda
helpers
Dsite
Dsite è un framework di pubblicazione, basato sulle dlibs, che ha come scopo quello di
velocizzare lo sviluppo di siti web e applicazioni, incoraggiando il riutilizzo del codice e
separando il più possibile la logica dalla presentazione.
Dsite implementa la classica architettura MVC, utilizzando come model oggetti ActiveDB,
come view templates di smarty ( http://www.smarty.net )
L'architettura di Dsite prevede un sistema di plug-in per potere espandere velocemente,
senza bisogno di agire a basso livello, il framework.
Struttura delle directory
cache
Contiene le directory in cui le varie cache di Dsite vengono salvate. In particolare:
smarty: contiene i templates compilati e le cache delle view (i templates di smarty)
imagecache: contiene le cache dell'imageserver
website: contiene le cache delle pagine
config
Contiene tutti i files con le configurazioni di base per Dsite. Normalmente Dsite è in grado
di funzionare, eccetto per quello che riguarda il database, senza necessità di alterare i files
di configurazione. La directory di installazione e tutti i path necessari vengono determinati
automaticamente.
autoload.php: contiene la funzione __autoload che serve a dsite per l'inclusione
automatica delle classi.
autosetup.php: al momento non utilizzato.
cache.php: contiene la configurazione delle cache delle pagine html. Tramite
questo file è possibile stabilire quali pagine o blocchi di pagine devono essere
cachate, e il loro tempo di expire.
database.php: contiene la configurazione dei “wrapper” usati per collegarsi ai
database utilizzati da dsite.
general.php: contiene la configurazione di tutti i path utilizzati dal framework, tra
cui l'include path. E' molto importante che le Dlibs si trovino o nel path di sistema,
specificato nel php.ini, o nel path specificato in questo file di configurazione.
private.php: file da utilizzare per tutte le configurazioni personalizzate.
libs
Nella directory libs si trovano tutte le librerie e i plug-in che costituiscono il cuore di Dsite.
In generale normalmente non è necessario modificare nessuno dei file presenti in questa
Directory.
website
Questa directory contiene il “sito web” vero e proprio. E' qui che verrà svolta la totalità, o
quasi, del lavoro necessario a costruire un sistema basato su Dsite. Le directory principali
sono “controllers”, “models” e “views” che contengono le componenti omonime della
struttura MVC. Tutte le altre directory sono directory di appoggio o di configurazione.
amp
Cartella di Anarchy Media Player ( http://an-archos.com/anarchy-media-player/ ), utilizzato
molto spesso nei progetti con Dsite.
controllers
Contiene i controller di Dsite.
files
Normalmente utilizzata per contenere tutti i files che devono essere pubblicati sul sito.
js, pics, styles
Directory utilizzate per javascript, fogli di stile e immagini utilizzate dai templates (views)
logs
Normalmente i due log di base di Dsite, dsite.log e error.log vengono creati in questa
directory. Si deve utilizzare questa directory anche per tutti gli altri log “custom”.
models
Contiene i modelli di Dsite. Per dsite un modello è una classe che estende ActiveDB (o
una sua classe derivata). All'interno di models è presente una directory autoload. Tutti i
modelli all'interno di essa saranno istanziati in automatica e passati automaticamente a
views e controllers, ad ogni richiesta di url. I modelli che si trovano nella radice dovranno
invece essere istanziati manualmente. In generale è buona prassi, per questioni di
performance, utilizzare l'autoload dei modelli solo dove necessario.
plugin-config
Come già accennato in precedenza Dsite fa largo uso di plug-in per estendere le
funzionalità di base. In questa cartella si trovano tutti i files di appoggio relativi alle
configurazioni dei plug-in. Le interfaccie del back-end (Dcontent) e i file di configurazione
dell'image server si trovano in questa cartella.
variables
La directory variables contiene le “variabili” di configurazione del sito e i cataloghi delle
label statiche. Tramite i file contenuti in questa cartella è possibile creare parametri di
configurazione dipendenti dalla lingua selezionata in Dsite. In particolare catalogs.php
descrive le lingue supportate dal sito in questione, la lingua di default e le relative “label”
statiche per ciascuna lingua.
views
In questa directory si trovano le views, ovvero i templates (smarty) che implementano la
parte di rappresentazione del modello MVC.
urlmap.php
Questo file contiene il sistema di associazione url, controller, view utilizzzato da Dsite.
Tramite questo file è possibile ad esempio stabilire quale template caricare in base all'url
richiesto.
index.php
Questo è un file ad uso interno. Di fatto è il “gateway” verso il quale vengono indirizzate
tutte le richieste. il suo compito è quello di inizializzare Dsite e di istanziare tutte le classi
necessarie al corretto funzionamento del framework. In generale non dovrebbe mai essere
modificato durante lo sviluppo di una applicazione DSite.
Il primo test
Tentiamo a questo punto un primo test di Dsite. Per un corretto funzionamento è
necessario un ambiente che includa:
Apache
PHP5
mod_rewrite per apache
il primo file che dobbiamo includere nella directory di root di dsite, che non è incluso
nell'svn, è il file .htaccess che specifica il mapping delle directory e le necessarie regole di
mod_rewrite.
Un file di esempio si trova in config/htaccess_model. Il modello da utilizzare è il seguente:
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule index.html website/index.php [L]
RewriteRule ^files/(.*)$ website/files/$1 [L]
RewriteRule ^pics/(.*)$ website/pics/$1 [L]
RewriteRule ^styles/(.*)$ website/styles/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . website/index.php [L]
</IfModule>
Il file, in sostanza, non fa altro che reindirizzare rel richieste che non corrispondono ad un
file o cartella realmente esistente su website/index.php
Il file mostrato qui sopra assume che il sito di test si trovi sulla root del webserver. In caso
contrario, se ad esempio avessimo installato Dsite in /dsitetest, per accedervi tramite l'url
http://<mydomain>/dsitetest dovremmo cambiare la riga
con
RewriteBase /
RewriteBase /dsitetest/
Fatto questo assicuriamoci che al momento nessuna connessione con il database sia
attiva. Aprendo config/database.php assicuriamoci che la riga che inizializza il DBWrapper
di base (maindb) sia commentata.
define("DB_HOST",
define("DB_NAME",
define("DB_USER",
define("DB_PASS",
"localhost");
"DSiteTest");
"root");
"");
//DBManager::addConnection("maindb",new
MysqlDBwrapper(DB_HOST,DB_NAME,DB_USER,DB_PASS));
Fatto questo apriamo il file “website/urlmap.php” e facciamo in modo che contenga solo la
riga:
$website->registerUrl("^testpage$", array(Template => "testpage.html"));
Come ultima cosa creiamo un file chiamato website/views/testpage.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
<title>DSite testpage!</title>
</head>
<body>
<h1>Ciao Mondo!</h1>
</body>
</html>
ora, andando su http://myserver/testpage potremo vedere la nostra prima pagina.
Vediamo in dettaglio le procedure di mapping dell'url, per capire come funziona. La riga
$website->registerUrl("^testpage$", array(Template => "testpage.html"));
corrisponde alla funzione registerUrl($url_expression, $control_array,
$extradata_array) dell'oggetto base di Dsite, dove:
$url_expression è una stringa che rappresenta un url che deve essere “matchato” da
Dsite. La stringa può contenere i caratteri ^ e $ che rappresentano rispettivamente “inizio”
e “fine” come nelle regular expressions, e dei blocchi {nomevariabile} che rappresentano il
mapping tra tutto quello contenuto tra le parentesi {} e una variabile “nomevariabile”.
Tutte le volte che viene trovata una corrispondenza tra $url_expression e l'url di richiesta
verrà fermato il processo di matching e passato il controllo al controller e template
specificati. In caso non venga specificato un controller (come nel nostro caso) il controller
invocato sarà quello specificato dalla costante BASEC_NAME (config/general.php)
Prendiamo per esempio
$website->registerUrl("^{section}/news$", array(Template =>
"testpage.html"));
Questo mapping verrà attivato in caso gli url di richiesta siano:
http://myserver/products/news
http://myserver/events/news
http://myserver/team/news
ma non nel caso:
http://myserver/products/events
Inoltre nel caso dei primi tre match positivi la variabile “section” passata automaticamente
sia ai templates che al controller, avrà rispettivamente i valori di “products”, “events”,
“team”.
Per utilizzare una variabile che proviene dall'urlmap.php nei template basta utilizzare la
sintassi {$nomevariabile}. Possiamo ad esempio utilizzare:
website/urlmap.php
$website->registerUrl("^{section}/news$", array(Template =>
"testpage.html"));
website/views/testpage.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
<title>DSite testpage!</title>
</head>
<body>
<h1>Sei nelle news della sezione {$section}</h1>
</body>
</html>
Multilingua
Variabili di default
Modelli e templates
Controllers
ImageServer
Urlmap