You are on page 1of 45

1a lezione

 A scuola con PC Open

Web Developer PHP di Federico Pozzato

1 La scelta di PHP
itando testualmente la avremo gli strumenti di base 1 I listati
C prefazione del manuale uf-
ficiale di PHP.net: “L'obiet-
tivo principale del linguaggio
per migliorare i nostri siti e per
affrontare una delle più impor-
tanti funzionalità di PHP, ossia
completi
sono sul CD
PHP è di permettere agli svi- l'integrazione con i database e
luppatori Web di scrivere velo- in particolare con MySQL.
cemente pagine Web dinami-
che, ma con PHP si possono fa- La storia
re molte altre cose”. del linguaggio PHP
È in questo spirito che PC PHP è un acronimo ricorsivo
Open introduce nelle sue pagi- (tipico dell'ambiente open
ne questo minicorso di PHP, source) che significa PHP: Hy-
potente linguaggio di scripting pertext Preprocessor. Che cosa
open source, pienamente inte- sia un ipertesto è chiaro, men-
grabile con HTML (da cui la tre può lasciare perplessi il si-
propedeuticità del corso Web- gnificato di Preprocessor: PHP,
master, fornito sul CD Guida n. come ASP, è un linguaggio ser-
2 unito a questo numero, utile ver-side, ossia il codice PHP è
anche se non necessaria) e in- prima elaborato dal server e
dirizzato prevalentemente allo solo dopo indirizzato al brow-
sviluppo dei siti Internet dina- ser che ha chiamato la pagina. La pagina phpinfo.php è la prima pagina di questo corso realizzata in PHP
mici. PHP viene utilizzato an- In tal senso PHP elabora la pa-
che per creare scripting di ri- gina “prima” della sua visualiz-
ghe comando e applicazioni zazione. creare immagini, file PDF, fil- su macchine client con sistemi
client-side GUI (Graphical User È una caratteristica total- mati Flash, generare file basati operativi Windows, Linux, BSD
Interface) utilizzando le esten- mente diversa rispetto a lin- su XML, utilizzare i protocolli o Mac e interfacciabile con tut-
sioni PHP-GTK. Tralasciando guaggi come Javascript che in- di posta POP3 e IMAP (ne ve- ti i più popolari Web server.
queste due applicazioni spe- vece sono client-side, ossia in- dremo un'applicazione nella
cialistiche, vedremo come PHP teramente interpretati dai seconda parte del corso), com- Utilizzare PHP off line
offra strumenti professionali browser. Vedremo in seguito primere file in gzip e bz2, gesti- e scrivere i primi listati
molto evoluti per la gestione come questa caratteristica ser- re sessioni, utilizzare funzioni e I listati in PHP possono esse-
Web, pur mantenendo una ver-side consenta l'implemen- classi, fare uso della program- re creati utilizzando un qualsia-
struttura semplice, adatta an- tazione di strutture e funziona- mazione orientata agli oggetti e si editor di testo e salvando le
che a chi si avvicina per la pri- lità assolutamente inedite per naturalmente interagire con pagine con estensione .php.
ma volta a linguaggi di pro- chi è abituato a ragionare in tutti i database più diffusi. Per Proviamo a scrivere il nostro
grammazione di questo tipo. termini di HTML puro. alcune di queste funzioni biso- primo semplice listato (la parte
Alla fine di questo minicorso PHP consente, inoltre, di gna installare estensioni forni- PHP è in grassetto. Più avanti
te con il file binario di PHP e ne approfondiremo il significa-
quindi si dovrà verificare pres- to), salviamolo col nome ph-
IL CALENDARIO DELLE LEZIONI so il proprio Web provider l'in- pinfo.php (listato1) e poi visua-
GET e POST stallazione delle specifiche li- lizziamolo col nostro browser:
 Lezione 1: - Esempi brerie (ad esempio quelle gra-
- La scelta di PHP fiche). LISTATO 1 (phpinfo.php)
- PHP con un server off line PHP ha ormai quasi 10 anni <html>
- La prima pagina PHP: Le prossime puntate di storia alle spalle (è stato <head>
inseriamo PHP in HTML Lezione 2: Approfondiamo creato nel 1994 da Rasmus Ler- <title>Prova PHP</title>
- Funzioni base e variabili PHP dorf e la prima distribuzione ri- </head>
- I costrutti di controllo: Lezione 3: PHP e i database sale al 1995; sito di riferimento: <body>
if else, while, do until, www.php.net), sposa appieno <?php
foreach Lezione 4: PHP e MySql la filosofia open source ed è di- phpinfo();
- I form: Lezione 5: Gestire un sito stribuito con licenza GPL. È un ?>
passaggio di dati coi metodi dinamico con PHP e MySql linguaggio multipiattaforma, </body>
utilizzabile indifferentemente </html>
1a lezione

Sul vostro browser vedrete o stabile di PHP per il proprio si- ScriptAlias /php/ "c:/php/" IIS, PWS e Xitami
una pagina totalmente vuota stema direttamente dal sito uf- AddType application/x-httpd-php .php Con IIS, PWS e Xitami la vita è
oppure il listato esattamente ficiale: www.php.net. Action application/x-httpd-php più semplice rispetto ad Apa-
come è scritto qui sopra. Cos'è Al momento in cui scrivia- "/php/php.exe" che, sempre che ci si acconten-
successo? Abbiamo affermato mo, la release stabile è una ti dell'installazione minima (ge-
che PHP è un linguaggio ser- 4.3.x, in attesa del sospirato ri- sostituendo a c:\php la car- neralmente sufficiente per i no-
ver-side, quindi per visualizza- lascio della release 5. Trala- tella di installazione. PHP viene stri scopi).
re le pagine create abbiamo bi- sciamo l'installazione di PHP installato nella versione CGI: In questo caso si deve solo
sogno di tre strumenti: un ser- su Linux, in quanto è un'opera- fate ripartire il server Apache e eseguire l'installer PHP: duran-
ver Web, il supporto PHP (il zione generalmente eseguita in poi verificate se la pagina ph- te la procedura di installazione
parser, gli elementi di una frase automatico scegliendo gli op- pinfo.php viene visualizzata ci verrà chiesto se è presente
o di un’istruzione) attivato da portuni pacchetti della propria nella maniera corretta. un server da configurare con
parte del server scelto e un distribuzione, e dedichiamoci Questo tipo di installazione PHP. Scegliete IIS o Xitami e at-
browser. all'ambiente Windows. Nell'a- è giudicato non sicuro e meno tendete la conclusione dell'in-
Nel nostro esempio ci siamo rea download di www.php.net performante dell'installazione stall shield: da adesso saremo
serviti solamente del browser si trovano due file utilizzabili di PHP come modulo, però dal in grado di verificare off line le
che, da solo, non è in grado di con sistemi Windows: momento che ce ne serviamo nostre pagine PHP. Per verifica-
interpretare la pagina PHP e la • un file installer (come: php- solo per scopi didattici (esclu- re il funzionamento, fate partire
fa vedere come fosse un nor- 4.3.7-installer.exe). Questo file sivamente off line) va comun- il server, provate a inserire nel-
male documento HTML (quin- ha dimensioni minime (circa que bene per i nostri scopi. la cartella scelta come root dei
di, in questo caso, apparente- 1 MB), è direttamente esegui- Non è possibile, però, installa- documenti il file phpinfo.php e
mente vuoto) oppure come un bile nel sistema e configura re alcuna estensione. richiamatelo col browser: do-
file testo. Nel primo caso la pa- automaticamente i server IIS Il secondo metodo richiede vete ottenere l'immagine 1 della
gina sembra vuota, ma se an- e Xitami, consentendo l'in- il file zip binario. Per prima co- pagina a lato.
diamo a vedere il codice sor- stallazione come versione sa si deve scompattare il file in L'installazione delle esten-
gente (ogni browser consente CGI per il server Apache. L'in- una cartella tipo c:\php, quindi sioni implica l'utilizzo del file
di farlo selezionando l'apposita staller non comprende le copiare il file php.ini-dist nella zip binario e qualche passo
voce presente nei menu) ve- estensioni di PHP. %SYSTEMROOT% (per Win- “manuale” aggiuntivo. Non la
dremo il listato 1. Per vedere in- • un file zippato contenente il dows 2000 è C:\WINNT) modifi- trattiamo in questa sede, ma è
vece la pagina PHP interpretata codice binario (come: php- candone il nome in php.ini. Al- comunque presente il file in-
nella maniera esatta, avremmo 4.3.7-Win32.zip). Questo file tra operazione da compiere è stall.txt che vi assiste passo pas-
dovuto per prima cosa caricare ha dimensioni ben più consi- copiare il file php4ts.dll nella so.
la pagina phpinfo.php su un ser- stenti (circa 7 MB), ma con- cartella c:\php\sapi. Ultimi
ver Web (abilitato per la tradu- sente l'installazione (manua- sforzi: editare il file httpd.conf Estensioni
zione delle pagine PHP) e poi le) di tutti i moduli. del server Apache (Start > Pro- Per utilizzare le estensioni
richiamare la pagina col brow- grammi > Apache > Configure > si deve effettuare l'installazione
ser (vedi disegno a fondo pagi- Il server Apache Edit the httpd.conf configuration del parser PHP tramite il file zip
na). Avremmo ottenuto quanto Come ASP richiamava il ser- file) e, dopo essersi posiziona- binario. Andrà poi modificato il
visibile nell'immagine 1: la no- ver IIS, così PHP richiama il ti nella sezione LoadModule, ag- file php.ini (dalla %SYSTEM-
stra prima pagina ci restituisce server Apache. Tuttavia, non giungere le seguenti righe (per ROOT%) inserendo l'indicazio-
tutte le caratteristiche della esiste al momento una proce- Apache 2.0.x): ne C:\php\extensions dopo l'u-
versione PHP installata sul ser- dura automatica per configura- guale nella riga che inizia con
ver Web. re il server Apache, sia esso LoadModule php4_module extension_dir =. Fatto questo,
Per la maggior parte delle 1.3.x o 2.0.x (supporto piena- c:/php/sapi/php4apache2.dll [o sempre nel file php.ini, cercare
persone è certamente impro- mente abilitato solo con una php4apache.dll per Apache 1.3.x] la sezione Windows extensions
ponibile pensare di poter im- versione di PHP oltre la 4.3.1). AddType application/x-httpd-php .php e togliere il punto e virgola da-
parare a programmare in PHP Si può procedere in due mo- vanti alle estensioni da abilita-
restando connessi a Internet, di, configurando PHP in versio- Facciamo le necessarie veri- re (ad esempio, per utilizzare le
vuoi a causa dei costi, vuoi per ne CGI (installazione più sem- fiche, dopodiché siamo pronti funzioni PDF bisogna abilitare
la scomodità di dover ogni vol- plice) o come modulo (installa- per iniziare. l'estensione php_pdf.dll). 
ta caricare le proprie pagine zione consigliata per motivi di
via FTP (o con upload dedicati) sicurezza).
1 Caricamento pagina 3 Il server, ricevuta la richiesta, chiede
per poi richiamarle tramite Nel primo caso utilizziamo il
sul server (via FTP) al parser di interpretare la pagina sorgente
browser (vedi disegno A ). file Installer. Eseguiamolo (ri-
Risulta quindi necessario in- cordandoci la cartella dove INTERNET
stallare un server sul proprio PHP verrà installato: C:\PHP va PAGINA
4 Il parser
SORGENTE
PC, col supporto alle pagine benissimo, ma potete cambiar- PHP PHP
PHP per le operazioni di par- la a piacere) e arriviamo al ter- Server Parser restituisce
sing. L'installazione di un ser- mine dell'installazione (anche WEB PHP
al server
ver sul proprio PC è già stata scegliendo l'opzione di confi- la pagina
descritta nella 7a lezione del gurazione automatica di Apa- interpretata
2 Richiesta pagina
corso Webmaster e la si dà per che, il software vi risponderà
da parte del browser
acquisita (l'installazione del che questa procedura non è
server Web va fatta prima di ancora applicabile). Ora dove- 5 Il server
PHP). Vediamo adesso come te editare il file httpd.conf del restituisce al
installare il parser, con indica- server Apache (Start > Pro- Schema per la BROWSER browser la pagina
zioni riguardanti tre server: grammi > Apache > Configure > UTENTE
interpretata dal
Apache, Xitami e IIS di Micro- Edit the httpd.conf configuration visualizzazione parser (NON viene
soft. file) e, dopo esservi posiziona- restituita la pagina
La prima regola fondamen- ti nella sezione ScriptAlias, ag- di pagine PHP sorgente in PHP)
tale è scaricare l'ultima release giungete le seguenti righe:
1a lezione

2 La prima pagina in PHP


a prima pagina PHP, in stamente, non c'è alcuna trac- output del parser: che in questo caso deve essere

L realtà, l'abbiamo già realiz-


zata (la solita phpinfo.php)
e la possiamo quindi analizza-
cia.
Notate il “;” al termine della
riga compresa nei tag: tutte le
LISTATO 3
<?php
attivata un'apposita opzione
del parser (asp_tags = On), con
gli stessi problemi di sicurezza
re. La parte iniziale e la parte fi- istruzioni PHP terminano con echo “<h1>Ciao PC OPEN</h1>”; già indicati per gli short tag.
nale comprendono solo tag e questo segnale di fine riga. Il ?> In tag.php trovate riuniti in-
contenuti HTML, mentre la “se- tag di chiusura ?> fa anche da sieme questi ultimi tre modi di
zione” PHP, quella interpretata “;” e quindi per l'ultima istru- Per indicare inizio e fine indicare il codice PHP (vedi li-
dal parser tramite il server e re- zione prima della chiusura si della sezione PHP stato 4).
stituita poi al client browser, potrebbe anche eliminare il “;”, Ci sono altri sistemi per in- Per buona regola, è sempre
viene chiaramente identificata però è certamente meglio non dicare l'inizio e la fine della se- bene utilizzare <?php e cercare
dai tag <?php (inizio sezione prendere certe abitudini e usa- zione PHP: di essere il più ordinati possi-
PHP) e ?> (fine sezione PHP). re tutta la sintassi normalmen- • tag brevi (short tag): bile, nell'eventualità di dover
Questi tag possono essere te richiesta. basta indicare <? e ?>. Per fare delle modifiche a distanza
aperti e chiusi quante volte si Un secondo esempio, hel- usarli deve essere apposita- di tempo.
vuole in un listato HTML: ai fini lo.php, ci consente di introdur- mente configurato il parser Per inserire dei commenti si
dell'efficienza nell'elaborazio- re la funzione echo che ha lo PHP del server Web ospitante. premettono al commento le
ne della pagina, infatti, è meglio scopo di restituire un output Generalmente è così, ma l'uso doppie slash //.
uscire dalla modalità PHP se si (listato 2 - hello.php): di questi short tag è comunque
devono passare blocchi di con- sconsigliato per motivi di sicu-
tenuti HTML “puri” (vale spe- LISTATO 2 (hello.php) rezza: se, per qualunque moti- Curiosità
cialmente per pagine compli- <?php vo (manutenzione, aggiorna-
cate). echo “ciao PC OPEN”; mento, e così via), il parser non In un'ottica di filosofia open
Tutto quello che si trova ?> interpretasse più in maniera source si sente nominare
compreso tra i tag PHP viene corretta gli short tag, il vostro l'acronimo LAMP. Esso
quindi interpretato dal server e La funzione print() produce codice diverrebbe visibile a indica un gruppo
restituito al browser per la vi- esattamente lo stesso output. tutti (come nell'esempio visto di prodotti divenuti, nel loro
sualizzazione: la funzione ph- all'inizio). insieme, un riferimento
pinfo(), infatti, restituisce tutte È possibile anche introdurre • indicazione di script: per lo sviluppo di siti Web:
le caratteristiche settate per il dei tag HTML all'interno della <script language="php"> e
parser PHP installato nel ser- sezione PHP come si può vede- </script>. Non è sempre inter- Linux
ver. Può essere curioso esami- re da hello-html.php (listato 3). pretato correttamente quindi Apache
nare il sorgente di questa pagi- Andranno inseriti all'interno di evitiamolo. MySQL
na: sono tutti contenuti HTML echo in quanto questi tag • ASP tag: i tag sono gli stes- PHP
e della funzione phpinfo(), giu- HTML devono diventare un si usati per ASP: <% e %>. An-

3 Tipi di dato, variabili e operatori


er iniziare realmente a usa- riabile scalare che abbiamo a

P
booleano (boolean), $1prova = 1;
re PHP e scoprirne le ca- disposizione: ossia assume solo valori ve- // il nome della variabile non
ratteristiche, abbiamo bi- ro (true) o falso (false). Il nu- è valido (numero dopo $)
sogno di spendere ancora qual- $prova1 = 12; mero 0 o una stringa vuota cor- Ridichiarando le variabili, o
che minuto per introdurre la // $prova1 è un tipo di dato intero rispondono al valore booleno concatenandole, PHP sceglie
gestione delle variabili. (integer), false; un numero diverso da 0 o sempre automaticamente il ti-
Diversamente da ASP, con in questo esempio è un inte- una stringa non vuota corri- po di dato da gestire. Se voles-
PHP non serve dichiarare espli- ro a base decimale, ma avrem- spondono al valore booleano simo sapere, ad esempio per
citamente le variabili indican- mo potuto fare una dichiara- true. motivi di debug, quale sia il ti-
do nome e tipo, ma, più sem- zione con le notazioni esadeci- po di dato di una certa variabi-
plicemente, basta assegnare al- male o ottale. In caso di supe- $prova4 = “pippo”; le, si può usare la funzione
la variabile il suo valore: sarà il ramento del limite massimo // $prova4 è un tipo di dato gettype:
parser ad attribuire alla varia- previsto per un intero, PHP as- stringa (string).
bile il giusto “tipo” (dichiara- segna automaticamente alla va- La stringa può essere defini- <?php
zione implicita). Tutte le varia- riabile il tipo float. ta utilizzando le virgolette sin- $prova = 1,2;
bili vanno indicate col simbolo gole ' (single quotes) o le virgo- echo gettype ($prova); // si ottiene a
$ davanti al nome scelto (il pri- $prova2 = 1,23; lette doppie “ (double quotes). video il tipo di dato: float
mo digit dopo $ non deve mai // $prova2 è un tipo di dato Nel proseguimento del corso si ?>
essere un numero). a virgola mobile (float). userà la seconda notazione che
permette, tra le altre cose, di Il tipo può essere imposto
Tipi di variabili scalari $prova3 = TRUE; inserire dei nomi di variabili al- mediante l'istruzione settype
Vediamo i quattro tipi di va- // $prova3 è un tipo di dato l'interno della dichiarazione all'atto già della dichiarazione
1a lezione

(esplicita) della variabile o at- identificate da un numero. Per segnare a una variabile lo spe- metici, logici e di confronto.
traverso l'imposizione (ca- fare riferimento a un elemento ciale valore NULL. Per comodità sono stati rias-
sting) del tipo (boolean, int, specifico (per stamparlo, mo- Nell'ambito delle variabili, sunti nel riquadro della pagina
float, string, array, object, null): dificarlo e così via) si usa il co- oltre a quelle definite da noi successiva, indicando solo gli
strutto: troviamo le cosiddette variabi- operatori che verranno utiliz-
<?php li superglobals, arrays conte- zati nel corso; per tutti gli altri
setype ($prova, “int”); $array[n] nenti informazioni sul Web ser- operatori (e per la loro prio-
$prova = 1,2; con n valore intero che parte da 0. ver, sull'ambiente di utilizzo e rità) fare riferimento al manua-
echo $prova; // si ottiene a video sugli input degli utenti. Alcuni le di PHP.net.
il valore del tipo “int”: 1 Creare un array come tabella esempi si possono vedere (coi
?> di hash è altrettanto semplice e relativi valori) aprendo la no- Costanti
versatile, ma in questo caso ci stra prima pagina creata (ph- Per alcune esigenze potrem-
<?php dovremo preoccupare di indi- pinfo.php), e altri li vedremo in- mo avere bisogno di definire
$prova = 1,2; care anche il valore (sia esso troducendo i form e le sessioni. delle costanti e non delle varia-
$intero = (int) $prova; un numero o una stringa) da Quasi tutti questi array super- bili. In questo caso il costrutto
echo $intero; // si ottiene a video assegnare alla chiave dell'ele- globali iniziano con un under- da usare è:
il valore del tipo “int”: 1 mento dell'array: score: $_POST, $_GET, $_SES-
?> SION, S_SERVER. define (“nome”, valore);
$hash_a = array (“italia” => ”roma”, echo nome;
Variabili di tipo composto “francia” => ”parigi”, “spagna” => Operatori
Oltre alle variabili di tipo ”madrid”, 12 => “pippo”); Gli operatori consentono di Valore può essere solo di ti-
scalare, ci sono due variabili di $hash_b[“italia”] = “roma”; eseguire operazioni sulle varia- po scalare; nome non è prece-
tipo composto: array e object. $hash_b [“francia”] = “parigi”; bili, operazioni non solo di na- duto dal simbolo $ ed è case
Array non è solo il classico $hash_b[12] = “pippo”; tura numerica (esempio: cal- sensitive.
vettore (ossia una lista di ele- coli aritmetici) e testuale
menti individuati da un indice La stampa dell'hash la pos- (esempio: concatenazione), ma Applicazione:
numerico avente numero ini- siamo vedere nell'esempio ha- anche operazioni di controllo immagine random
ziale 0), ma può essere anche sh.php (listato_06). Per elimina- (esempio: logica binaria) e con- Vediamo finalmente un
una tabella di hash (una map- re, modificare, stampare i dati fronto (esempio: confronto di esempio pratico di quanto ab-
pa), dove un elemento è indivi- dell'hash vi faremo riferimento valori e tipi). biamo imparato: immaginiamo
duato da una chiave non ne- con i due costrutti (diversi a La concatenazione è senza di avere inserito in una certa
cessariamente numerica. Ciò seconda del tipo di chiave): dubbio una delle operazioni cartella del nostro spazio Web
lascia estrema libertà di utiliz- più usate: le variabili in PHP una serie di immagini contenu-
zo del tipo array, ma impone $array[numero] possono essere concatenate te nella directory Immagini e
anche di prestare attenzione $array[“chiave”] // o: $array['chiave'] usando il segno “.”: aventi nome vacanza_x.jpg do-
quando viene richiamato un ve x è un numero intero pro-
valore. Le chiavi possono esse- Si rivelerà utile questa pos- <?php gressivo che parte dal valore 1.
re valori sia numerici, sia di ti- sibilità che ci concede PHP: do- $a = “PC OPEN”; Sulla nostra home page è vi-
po stringa; gli elementi dell'ar- po aver dichiarato un array ha- $b = “una rivista di informatica”; sualizzata una di queste imma-
ray possono essere di qualun- sh_a, possiamo inserire gli ele- $c = $a.”, “.$b; gini, ma noi vorremmo, per
que tipo (anche altri array). menti anche senza fare riferi- echo $c; // si ottiene come output: rendere il sito più attraente e
Se vogliamo creare un vetto- mento a una chiave specifica: PCOPEN, una rivista di informatica farlo sembrare sempre diverso
re, lo possiamo fare in maniera ?> e aggiornato, fare apparire
esplicita (indico la parola chia- $hash_a[ ] = “topolino”; un'immagine diversa ogni volta
ve array) o implicita (assegno i Notate l'inserimento, tra vir- che l'home page viene richiesta
valori alla variabile che sarà il In questo caso la chiave del- golette doppie, della virgola e (o quando viene fatto il refre-
vettore): l'elemento sarà il numero inte- dello spazio vuoto per meglio sh). La situazione di partenza è
ro successivo al numero intero visualizzare a video le due va- visibile nella pagina intro.html
$vettore_a = array (2, 5, 7, 9, 11); più alto già presente nell'hash. riabili. (listato 8) che mostra l'immagi-
// dichiarazione esplicita con elementi Pertanto, come mostrato dal- Lo stesso risultato lo si sa- ne (un quadrato colorato) va-
solo numerici l'array hash_b dell'esempio ha- rebbe ottenuto utilizzando op- canza_1.jpg al centro della pa-
$vettore_b = array (2, “pippo”, true, sh-due.php (listato 7), possia- portunamente la funzione echo gina.
1.24, array (1,2,3)); // dichiarazione mo creare facilmente un array (senza però utilizzare la varia- Dovremo fare in modo che il
esplicita con elementi misti assegnando come chiave ini- bile $c): valore x sia generato in manie-
$vettore_c = array (0 => 2, 1 => ziale un numero diverso da 0. ra random a ogni chiamata del-
“pippo”, 2 => true); // notazione per Vedremo come questo possa echo ”$a, $b”; // equivalente a: echo la home page. Utilizzeremo a
indicare le chiavi del vettore (potevano essere utile quando parleremo $a.”, “.$b; tale scopo la funzione
essere omesse senza problemi) di date. rand(y,z) di PHP, supponendo
$vettore_d[0] = 2; // dichiarazione Il tipo di dato object lo ana- Si può anche “concatenare” di avere cinque immagini nel
implicita del primo elemento del lizzeremo nel prosieguo del una stringa con se stessa con server Web. Il risultato è visibi-
vettore_d corso parlando delle classi. questa sintassi abbreviata: le aprendo la pagina
$vettore_d [1] = “pippo”; random.php (listato 9): la parte
// dichiarazione implicita del secondo Tipi di variabili speciali <?php che ci interessa, quella che ge-
elemento del vettore_d Per finire l'analisi, vi sono $a = “PCOPEN “; nera il numero casuale com-
ancora due tipi speciali di va- $a. = ”amico” // equivale a: $a = preso tra 1 e 5 e che visualizza
Per visualizzare un array e le riabili: resource e null. Il primo $a.”amico”; l'immagine è la seguente:
sue chiavi usiamo la funzione è creato e usato da una serie di echo $a; // si ottiene a video: PC
print_r, come indicato nell'e- funzioni ben definite (per ap- OPEN amico <?php
sempio vettore.php (listato 5). profondimenti vedere le ap- ?> $num=rand(1,5);
Dagli esempi qui sopra ottenia- pendici del manuale PHP), // rand(min,max) genera un numero
mo coppie che sono sempre mentre il secondo serve ad as- Vi sono poi operatori arit- casuale intero compreso tra min e max 
1a lezione

 inclusi te, la quale inizializza un array


echo "<img src='immagini/ con tutti i valori estratti da uno
vacanza_".$num.".jpg'>"; // timestamp specificato. Operatori aritmetici
gli attributi HTML vanno indicati usando
gli apici singoli e non le virgolette Esempi di utilizzo Poniamo: $a=5 e $b=3
?> di date in PHP
Trattare con le date non è $c=$a+$b; // somma: $c=8
Riprenderemo l'esempio, semplice, ma può essere molto $c=$a-$b; // sottrazione: $c=2
per approfondirlo e migliorar- utile saperlo fare. Ecco quindi $c=$a*$b; // moltiplicazione: $c=15
lo, dopo aver introdotto il co- due esempi per fare un po' di $c=$a/$b; // divisione: $c=1,66
strutto while. pratica. $c=$a%$b; // modulo: $c=2
Oggi.php (listato 10): serve a
Le date esprimere la data odierna uti-
Come avrete notato, PHP lizzando i nomi estesi dei gior- Pur non essendo un operatore va ricordato anche:
non propone nessun tipo di va- ni e dei mesi, in italiano. La fun-
riabile date o time, ma molto zione date non è sufficiente $c=int($a/$b); // quoziente intero della divisione: $c=1
probabilmente avremo spesso perché estrae sì questi dati, ma
bisogno di utilizzare questi for- in lingua inglese. Si potrebbe
mati data e tempo. usare setlocale e strftime, ma Utilizzeremo anche gli operatori di incremento e decremento:
A tale scopo useremo le fun- preferiamo usare un altro si-
zioni di data e ora previste da stema che ci consente anche si $c=++$a; // $c=6 (pre-incremento) e $a=6
PHP. La principale è senza dub- utilizzare gli array. Date ci con- $c=--$a; // $c=4 (pre-decremento) e $a=4
bio sente di estrarre il valore nu- $c=$a++; // $c=5 (post-incremento) e $a=6
merico (senza zeri) sia del gior- $c=$a--; // $c=5 (post-decremento) e $a=4
date (formato, timestamp); no della settimana (0=domeni-
ca) che del mese, quindi per
in grado di restituire tutti i prima cosa creiamo due array
possibili valori in termini di da- (quello dei mesi ha il primo nu-
ta e tempo estraendoli da uno mero della chiave corrispon- Operatori logici
timestamp. Il timestamp, nato dente a 1) e poi il gioco è fatto:
nel modo UNIX, rappresenta il Poniamo: $a=true e $b=false
numero di secondi trascorsi <?php
dal 1/1/1970 (la cosiddetta $giorno = array ("domenica", $c=$a and $b; // AND: $c=false
Unix Epoch) ed è valido fino al "lunedì", "martedì", "mercoledì", $c=$a or $b; // OR: $c=true
2037 (va bene, quindi, per le "giovedì", "venerdì", "sabato"); $c=! $a; // NOT: $c=false
nostre esigenze attuali). Se non $mese = array (1 => "gennaio",
indichiamo il timestamp, date "febbraio", "marzo", "aprile",
considererà giorno e ora di "maggio", "giugno", "luglio",
quel preciso momento del ser- "agosto", "settembre", "ottobre",
ver Web ospitante PHP. Se vo- "novembre", "dicembre");
lete inserire un vostro time- $giorno_mese = date ("d"); Operatori di confronto
stamp, dovete usare la funzio- $anno = date ("y");
ne mktime() con questa moda- $mese_nome = $mese[date("n")]; Useremo questi operatori coi costrutti di controllo.
lità: // restituisce il nome del mese
$giorno_nome = $giorno[date("w")]; $a == $b; // true se $a uguale a $b
mktime (ora, minuti, secondi, mese, // restituisce il nome del giorno della
giorno, anno, ora_legale) // ora_legale settimana
(valore -1 o 0) può essere omesso: echo "Ciao, oggi è $giorno_nome NB: l'operatore == effettua un controllo di confronto senza
PHP cercherà di ricavare il valore dal $giorno_mese $mese_nome modificare il valori di $a e $b, mentre l'operatore = effettua
sistema $anno"; un'assegnazione di valore.
?>
Date fornisce una lunga lista $a <> $b; // true se $a diverso da $b
di formati tra cui scegliere, co- counter.php (listato 11): ser- $a < $b; // true se $a minore di $b
me: ve a organizzare un elemento $a > $b; // true se $a maggiore di $b
che funga da contatore per in- $a <= $b; // true se $a minore o uguale a $b
$timestamp = mktime (12, 0, 0, 2, dicare, ad esempio, quanti gior- $a >= $b; // true se $a maggiore o uguale a $b
11, 2004); // timestamp del ni mancano a una data partico-
12/02/2004, ore 12.00 lare. Per prima cosa dovremo
ricavare il timestamp della data
echo date (“d-m-y”, $timestamp); odierna (in un orario x) e della
// a video: 11-02-04 data da raggiungere (sempre
echo date (“D d, F Y”, $timestamp); allo stesso orario x. Qui pren-
// a video: Wed 11, February 2004 diamo come riferimento il 31
echo date (“H:i:s”, $timestamp); dicembre del 2004). Facendo
// a video: 12:00:00 la differenza tra questi time-
echo date (“w, z”, $timestamp); stamp otterremo il numero di ci separano dal nostro riferi- $fine = mktime
// a video: 3 (giorno della settimana), secondi che separa le due date, mento. I dettagli sono com- (12,0,0,12,31,2004,0);
41 (giorno dell'anno) quindi dividendo per il numero mentati nel listato: $diff=($fine-$inizio)/86400;
di secondi di un giorno <?php echo "Alla fine del 2004 mancano
Può essere interessante an- (60*60*24 = 86.400 secondi) $inizio = mktime(12,0,0,date(“n”), $diff giorni";
che studiare la funzione getda- avremo il numero di giorni che date(“j”), date(“Y”), 0); ?>
1a lezione

4 I form
er interagire con chi acce- trasmettere, in maniera total- 2

P de alle nostre pagine ab-


biamo a disposizione, tra-
mite HTML, una serie completa
mente trasparente all'utente,
tutti i dati compilati nel form
senza alcun limite di spazio,
di campi da compilare. L'utente mentre il metodo get trasferi-
ci fornirà quindi i dati che ver- sce i dati visualizzandoli sulla
ranno usati come base per ela- riga di indirizzo del browser (e Metodo GET
borare le azioni successive. col limite di soli 256 caratteri
Come webmaster dobbiamo trasmissibili). Per vedere la dif-
compiere questi passaggi: crea- ferenza fate riferimento a po- 3
re il form di inserimento dati, st.php (listato_12, è un form con
acquisire i dati (registrandoli metodo post) e a get.php (lista-
nelle forme opportune ed even- to_13, è un form con metodo
tualmente validandoli), fornire get): entrambi hanno come at-
una risposta all'utente. La crea- tributo action la pagina
zione del form si effettua con test.php, ma la differenza di tra- Metodo POST
HTML e la si dà per acquisita smissione dei dati la notate sul-
(vedi corso webmaster). Fon- la riga del browser (vedi imma-
damentale per passaggio, regi- gini 2 e 3). non danno: una volta registrato biamo aspettare di aver intro-
strazione e utilizzo dei dati è la un dato del tipo $_REQUE- dotto i costrutti di controllo.
prima riga dell'istruzione form, Tre istruzioni ST[“nome_dato”] possiamo poi
e in particolare la parola action Una volta trasferiti i dati, do- richiamarlo nella pagina come Modifica dello stile
e i due metodi get e post: vremo essere in grado di acce- fosse una variabile appena di- di una pagina Web
dervi: PHP mette a disposizio- chiarata, ossia con la forma: Un altro interessante esem-
<form action=”test.php” ne queste tre istruzioni “su- $nome_dato pio lo possiamo immaginare
method=”post”> perglobali”: sfruttando le caratteristiche
Conto alla rovescia dei fogli di stile: vogliamo, in-
Questa riga indica, una volta $_GET[“dato”] // per form con modificato fatti, dare la possibilità al no-
sottoscritti i dati con l'apposito metodo get Ora siamo in grado di intera- stro utente di visualizzare i no-
controllo submit, che il browser gire col nostro utente. Potrem- stri articoli riportati su pagina
verrà indirizzato alla pagina te- $_POST[“dato”] // per form con mo, ad esempio, aumentare l'u- Web con carattere, dimensioni
st.php sul CD (se action è metodo post tilità del “conto alla rovescia” e colori preferiti.
omessa la pagina cui l'utente presentato nella sezione prece- Faremo transitare il nostro
viene reindirizzato è la pagina $_REQUEST[“dato”] // sia per form dente, consentendo all'utente utente dalla pagina introduzio-
stessa che comprende il form) con metodo get che post di indicare lui stesso la data cui ne.html (listato_15) dove è pre-
e i dati passeranno col metodo fare riferimento. sente un form attraverso il
post. $_REQUEST concede una Dobbiamo solo stare attenti quale si dovrà scegliere il ca-
Il metodo post consente di possibilità che $_GET e $_POST ai dati inseriti (sia in termini di rattere poi visualizzato nella
formato che di valori consenti- pagina articolo.php sul CD.
ti) e quindi useremo dei con- La scelta dei caratteri è ri-
trolli con caselle combinate (le dotta alle quattro famiglie
POST e GET in PHP liste a discesa), come nell'e- (arial, verdana, times, courier)
sempio inserisci.html (listato generalmente visualizzate da
Fino alla versione 4.2.0, PHP protette. 14). I valori inseriti saranno tutti i browser, e i colori con-
concedeva sempre e comunque Per utilizzare il “vecchio” passati attraverso il metodo sentiti sono espressi in termini
di richiamare i dati inseriti sistema bisogna fare post alla pagina conto_rove- esadecimali, anche se l'utente
nei form con la forma una modifica su php.ini, scia.php sul CD. È possibile an- vede delle descrizioni “norma-
$nome_dato. Ora questa sostituendo il valore off che inserire date senza senso li” (bianco, nero, giallo, ...).
possibilità, salvo il caso visto a on sulla riga register_globals (ad esempio 31 giugno): la fun- Scelta la combinazione voluta,
con $_REQUEST, non è più (il valore valido per il vostro zione timestamp si occuperà di la pagina articolo.php verrà vi-
concessa per motivi sistema lo potete vedere anche trasformare l'errato inserimen- sualizzata di conseguenza tra-
di sicurezza. Per capirne controllando la pagina to nella data più vicina e visua- mite le indicazioni inserite nel
le implicazioni, immaginate visualizzabile usando la pagina lizzeremo questa data nella ri- foglio di stile incorporato:
che qualcuno avesse chiamato phpinfo.php). sposta. La data inserita dall'u-
la pagina test.php senza Sottolineiamo però, ancora tente nel form viene così ripor- <style>
passare attraverso i form: una volta, come sia meglio tata, tramite $_POST, nella pa- span.font {
semplicemente scrivendo comunque abituarsi a usare gina indicata da action: font-family: <?php echo
http://www.xxxxx.it/test.php?n $_POST e $_GET, sia per $_POST['carattere']; ?>;
ome=topolino questo utente evitare problemi di sicurezza, // $fine è il timestamp della data font-size: <?php echo
smaliziato sarebbe riuscito sia per evitare che il vostro richiesta $_POST['dimensione']; ?>px;
ad attribuire alla variabile provider, magari aggiornando $fine = mktime (12,0,0,$_POST[ color: <?php echo $_POST['col_car']; ?>;
$nome il valore topolino. il parser PHP, cambi il valore 'mese'],$_POST['giorno'], }
Vi sono casi in cui questa di register_globals da on a off $_POST['anno'],0); body {
possibilità conduce a eventi lasciandovi un bel po' background-color: <?php echo
assolutamente indesiderati, di problemi sulla visualizzazione Sarebbe comunque da impe- $_POST['col_sfondo']; ?>;
compreso l'accesso a pagine del vostro sito! dire l'inserimento di date non }
valide, ma per fare questo dob- </style> 
1a lezione

 L'esempio può essere am- sibile variare la dimensione (in dimensione dei font cui è stata tium) per accrescere l'usabilità
pliato coinvolgendo tutte le ca- pixel) del carattere. assegnata una dimensione fis- del Web a persone cui può es-
ratteristiche della pagina co- Si potrebbe pensare che sa (in punti o pixel). sere assolutamente necessario
me indicato dalle proprietà dei questa indicazione definisca la scalare i caratteri.
CSS. Anche qui, però, mancano dimensione del carattere in Le disposizioni del W3C Tenete poi presente che una
le strutture di controllo: cosa maniera fissa, indipendente dal Chi sbaglia? Diversamente certa dimensione in pixel può
succede se si accede alla pagi- browser. da quanto si potrebbe pensare, essere splendida per certe ri-
na senza passare attraverso In realtà se aprite la pagina è Explorer a non rispettare i soluzioni video, ma per altre
l'introduzione? Sarà il browser articolo.php con Mozilla (oppu- dettami stabiliti per i browser può rivelarsi non adatta perché
a decidere la visualizzazione, re Opera o Firefox) vedrete che Internet: anche se questa pos- troppo piccola.
ma chiaramente questa è una usando le combinazioni CTRL+ sibilità di ridimensionamento Non prendetevela, quindi, se
condizione inaccettabile per il + o CTRL+ - i caratteri aumente- manda in crisi i webmaster (de- dopo aver speso giorni e giorni
webmaster. ranno o diminuiranno di di- siderosi di mantenere il layout a stabilire la giusta visualizza-
mensione. studiato per la pagina), essa è zione della pagina fissando tut-
Accessibilità dei siti Web Microsoft Explorer, invece, espressamente richiesta dal ti i font, un semplice CTRL+ +
Nell'esempio indicato è pos- non modifica assolutamente la W3C (World Wide Web Consor- potrà scompaginare tutto.

5 Costrutti di controllo
er costruire script avanza- lo. Viene definita una condizio- to.php (listato 16): creiamo due Questo costrutto è molto

P ti bisogna padroneggiare
assolutamente le strutture
di controllo, ossia quelle istru-
ne: se (if) è rispettata (condi-
zione vera) viene eseguito il
codice tra le parentesi graffe
numeri interi casuali $a e $b
compresi tra 1 e 4 e verifichia-
mo quale dei due sia più gran-
utilizzato per leggere le liste:
ad esempio si usa while per
mandare a video tutti i record
zioni che consentono di ese- dopo la if, altrimenti si esce de: di una tabella terminando l'e-
guire delle azioni solo a fronte dalla if senza eseguire il codice In alcuni frangenti si dimo- secuzione quando la tabella è
della verifica di particolari con- o viene eseguito del codice al- stra utile usare la parola chiave vuota (vedremo questo utiliz-
dizioni. ternativo (else): exit all'interno di una condizio- zo nelle lezioni dedicate a My-
L'esempio tipico è dato dalla ne: quando viene incontrata SQL).
pagina protetta da password: if (condizione) { questa istruzione, il server Con il costrutto while siamo
volendo descrivere a parole l'a- codice da eseguire se condizione blocca la “traduzione” della pa- finalmente in grado di miglio-
zione connessa, essa suona co- è vera gina e la invia al browser client rare l'esempio creato per la vi-
me Accedi alla pagina solo se la } come definita in quel momen- sualizzazione random di una
password che hai fornito corri- else { to. Un esempio è disponibile in foto (random.php, listato_09).
sponde a quella registrata per il codice da eseguire se condizione controllo-exit.php (listato_17): Cosa succede, infatti, se in-
nome utente inserito. “Solo se” è è false se la prima condizione è soddi- seriamo altre immagini nella
il costrutto di controllo. } sfatta non posso più visualiz- cartella Web che abbiamo scel-
PHP ci fornisce tutti i co- zare quanto scritto dopo la to, sempre seguendo le stesse
strutti standard (for, if, while, Le condizioni if possono es- chiusura del ciclo if: logiche di numerazione?
switch) e un paio di istruzioni sere nidificate senza problemi Dovremmo correggere off-li-
estremamente utili (foreach e per creare strutture comples- if ($a>$b) { ne il listato di cui sopra, sosti-
isset) per accelerare i tempi di se. La condizione elseif con- echo "\$a=$a e \$b=$b:<br>"; tuendo al valore 5 il valore più
scrittura del codice. sente di aggiungere ulteriori echo "\$a è maggiore di \$b"; alto delle nuove immagini in-
condizioni da verificare prima echo "<p><h3> Verificata questa serite, per poi trasferire di
If – else – elseif di arrivare al codice else o di condizione blocco il codice successivo nuovo la pagina sul server so-
La condizione if (con l'even- uscire dal costrutto. usando exit. vrascrivendo la precedente.
tuale aggiunta di else o elseif) è Un esempio di utilizzo lo Non potete sapere cosa c'è scritto Facile, ma è una possibile fon-
la base dei costrutti di control- possiamo vedere in confron- dopo il blocco if!</h3>"; te di errori: PHP ci può rispar-
exit; miare questa operazione ren-
} dendo la nostra pagina valida
LISTATO 16 qualunque sia il numero di im-
While magini presenti nella cartella.
<?php Il costrutto del ciclo while è Per questo sfruttiamo le fun-
$a = rand (1,10); veramente semplice e al con- zioni per le directory (in parti-
$b = rand (1,10); tempo potente: le istruzioni colare opendir e readdir) e i co-
if ($a>$b) { contenute nel ciclo sono itera- strutti di controllo.
echo “$a=$a e \$b=$b:<br>\$a è maggiore di \$b”; // il carattere te finché la condizione è vera, Innanzi tutto usiamo open-
escape (\) serve a visualizzare come output simboli particolari come $ ogni volta andando a leggere dir per registrare (e validare) il
} (ordinatamente) il valore suc- percorso della cartella, e poi
elseif ($a==$b) { // notare l'operatore di confronto == cessivo della condizione. readdir per leggere il primo file
echo “$a=$a e \$b=$b:<br>\$a è uguale a \$b”; Quando la condizione diventa della directory.
} falsa il ciclo si arresta e prose- Qui interviene while: attra-
else { gue oltre: verso una condizione while su
echo “$a=$a e \$b=$b:<br>\$a è minore di \$b”; while (condizione) { readdir, la directory viene letta
} codice file dopo file e ogni riferimento
?> } è registrato su un array. Esau-
1a lezione

rita la lettura, il codice esce dal for (punto iniziale; condizione da LISTATO 20
ciclo while e possiamo final- rispettare; tipo di iterazione) {
mente definire $max, ossia il codice da eseguire if ($fine%2==0) { // controllo se nella cartella c'è un numero pari di immagini
numero di immagini che ab- } for ($i=2;$i<count($lista);$i=$i+2) { // il ciclo di for visualizza due file
biamo trovato nella directory ad ogni iterazione
Immagini. For si rivela utilissimo per $ordine=$i-1;
Ecco quindi la pagina ran- costruire strutture di pagina $j=$i+1;
dom-due.php (listato 18). di cui non possiamo conoscere echo "<span class='dispari'>File $ordine: $lista[$i]</span>";
La parte più utile da analiz- con anticipo tutti gli elementi: echo "<span class='pari'>File $i: $lista[$j]</span>";
zare è la seguente: stiamo parlando, quindi, di ve- }
ri e propri siti dinamici. }
while (false !== ($file = readdir($cartella))) { Per capire meglio, possiamo else { // il numero di immagini è dispari, quindi si deve aggiungere l'ultima riga
// il ciclo while verrà iterato finché costruire un esempio basan- dispari
la cartella non sarà stata interamente doci su quanto visto per il co- for ($i=2;$i<$fine;$i=$i+2) { // il ciclo for visualizza due file per ogni
letta. A ogni iterazione $file assume strutto while con la directory iterazione e si ferma prima dell'ultima immagine
il nome del file successivo. Immagini. $ordine=$i-1;
Con la prima iterazione creo l'array In questo caso, però, il no- $j=$i+1;
e registro il primo nome di file, stro scopo è ottenere la lista echo "<span class='dispari'>File $ordine: $lista[$i]</span>";
poi l'array viene riempito con i nomi delle immagini contenute nella echo "<span class='pari'>File $i: $lista[$j]</span>";
dei file seguenti cartella, visualizzandole nella }
$lista[ ]=$file; pagina Web elenco-dir.php. Qui $j=$i-1;
} trovate la parte del listato che echo "<span class='dispari'>File $j: $lista[$i]</span>";
// count conta il numero si riferisce al costrutto for (li- }
di elementi contenuti nell'array. Viene stato 19).
diminuito di due perché l'array della Possiamo migliorare la visi-
cartella contiene sempre le indicazioni bilità del nostro elenco visua-
UNIX "." e ".." lizzando i file alternativamente mero prefissato di immagini, o Dove sta la differenza? Nel
$max=count($lista)-2; su righe aventi colore di sfon- altri oggetti, per ogni pagina primo caso la variabile $mese
if ($max==0) { do diverso (elenco-dir-due.php, (ad esempio sei immagini per è valutata all'inizio del costrut-
echo "Attenzione: Non ci sono listato_20). Qui l'attenzione va pagina) e una barra di naviga- to e poi il valore è solo con-
immagini nella cartella"; posta nel conteggio delle righe zione per spostarsi tra le pagi- frontato con quelli delle istru-
} da mandare in output: se sono ne. zioni case, mentre nel caso di
else { pari verrà eseguito un ciclo for if la variabile $mese è valutata
$num=rand(1,$max); e usciremo dalla pagina, men- Switch e verificata ogni volta, con uno
} tre se sono dispari il ciclo for Il costrutto switch somiglia spreco di risorse e tempo di
dovrà fermarsi prima dell'ulti- a una serie di if di uguaglianza: elaborazione.
Ricordiamo che PHP 5, al ma riga, che andrà stampata a una variabile (array e object Notate la parola chiave
momento rilasciato solo come parte (listato 20). esclusi) viene confrontata con break: va inserita al termine di
release candidate, prevede una Un buon esercizio per verifi- dei valori predefiniti così da ogni blocco di codice case, al-
nuova funzione, scandir, in gra- care di aver compreso bene i eseguire differenti blocchi di trimenti il parser continuereb-
do di evitare questo passaggio concetti di cui sopra può esse- codice a seconda del valore be leggendo il blocco succes-
con while: scandir sarà infatti re il seguente (è una variazione assunto dalla variabile: sivo invece di uscire dal co-
in grado di leggere i contenuti sul tema di quanto appena vi- strutto.
di una cartella e registrarli di- sto): creare una galleria delle $mese=date('n'); È possibile definire un case
rettamente in un array senza immagini della directory, vi- switch ($mese) { con valore default: il codice
utilizzare altre funzioni. sualizzandole a due a due, una case 1: sarà eseguito quando tutte le
di fianco all'altra. echo “Siamo in Gennaio”; altre condizioni case si rivele-
For Chiaramente dovremo usare break; ranno false.
Il ciclo for consente di itera- le tabelle e/o i CSS, ponendo case 2:
re un'azione, definendo la con- attenzione all'eventuale ultima echo “Siamo in Febbraio”; Isset
dizione iniziale di un puntato- immagine dispari. La soluzione break; Abbiamo spesso la neces-
re, il controllo da fare e l'incre- da me proposta la trovate nel- case 3: sità di controllare, prima di
mento del puntatore dopo la pagina elenco-galleria.php echo “Siamo in Marzo”; compiere un'azione, se una va-
ogni ciclo. L'azione verrà ese- (sul CD). break; riabile è definita (anche se ma-
guita (e rieseguita) finché il Vedremo nelle prossime .................. gari con valore nullo) oppure
controllo darà risposta true al- puntate del corso come creare } se non lo è.
la verifica. una galleria con un certo nu- Questo controllo è assolto
Lo stesso risultato si sareb- semplicemente da isset in
be raggiunto con: combinazione con if: isset, in-
LISTATO 19 fatti, restituisce un valore true
$mese=date('n'); se la variabile cui fa riferimen-
echo "<h4>La cartella 'immagini' contiene questi file:</h4><p>"; if ($mese==1) { to esiste:
for ($i=2;$i<=count($lista)-1;$i++) { // il contatore $i parte da 2 echo “Siamo in Gennaio”;
perché i primi due valori registrati nell'array $lista sono } if (isset($variabile)) {
“.” e “..”, e non voglio visualizzarli if ($mese==2) { codice
echo “Siamo in Febbraio”; }
$ordine=$i-1; }
echo "---------------------------------------------------<br>"; if ($mese==3) { Possiamo usare isset per mi-
echo "<span class='output'>File $ordine: $lista[$i]</span><br>"; echo “Siamo in Marzo”; gliorare l'esempio in cui modi-
} } ficavamo la visualizzazione di
.................. un articolo. 
1a lezione

LISTATO 21 Per fare questo potremmo

<style>
usare un ciclo for (ma dobbia-
mo sapere quanti elementi I corsi
span.output {
font-family:
compongono l'array) o un ciclo
while (con una struttura non
Webmaster
<?php molto amichevole). Oppure un disponibili
if (isset($_POST['carattere'])) {
echo $_POST['carattere'];
semplice ciclo foreach (pagina
lista-disney.php, listato 22): nel CD
// valido solo se è stato sottoscritto il form e quindi $_POST esiste Un altro esempio concreto
} lo si ha in occasione della vali- Nel CD Guida 2 allegato
else { dazione dei dati passati attra- a questo numero di PC
echo "Arial"; verso un form: se vogliamo Open, all’interno della
// è la visualizzazione di default quando $_POST non esiste, porre tutti i campi di un form cartella PDF/Corsi, trovate
ossia non è mai stato cliccato il bottone “invia” del form come obbligatori, dovremo due corsi completi che
} controllare tutti i campi per ve- possono essere un utile
?>; rificare che sia stato immesso complemento al corso PHP.
} un valore, inserendo quindi Uno è il corso Web
</style> una serie di istruzioni if e/o is- Developer ASP, 97 pagine
set. Foreach ci viene in aiuto suddivise in quattro lezioni
per rendere la scrittura più agi- per capire come realizzare
le e per evitare banali dimenti- siti dinamici in tecnologia
LISTATO 22 canze, come si vede dalla pagi- ASP.
na check.php (listato 23):
$lista=array (“pippo”, “topolino”, “paperino”, “pluto”); Notate, nel ciclo if, la funzio-
foreach ($lista as $copia) { ne trim il cui scopo è eliminare
echo “Un personaggio Disney: $copia<br>”; tutti gli spazi vuoti all'inizio di
} un campo: in questo modo se
un utente compilasse il form
Si può utilizzare foreach anche per definire un secondo array contenente le chiavi solo con degli spazi vuoti, il no-
dell'array originale: stro test comunque non ne va-
liderebbe l'inserimento (una
$lista=array (“pippo”, “topolino”, “paperino”, “pluto”); funzione if semplice, invece, l'a-
foreach ($lista as $chiave=>$copia) { vrebbe fatto passare).
echo “Personaggio Disney numero $chiave -> $copia<br>”; Un controllo di questo tipo è
} sufficiente per la maggior parte
delle nostre esigenze, come ve-
dremo nella prossima puntata
del corso.
Introduciamo qui anche la
LISTATO 23 funzione die che interrompe
l'esecuzione della pagina vi-
if (!isset($_POST['nome'])) { sualizzando come output il co-
// serve solo alla prima chiamata della pagina dice chiuso dalle parentesi. Il corso Webmaster spiega,
die ("<p><h3>Tutti i campi vanno obbligatoriamente compilati</h3>"); Lo stesso compito era assol- invece, in 88 pagine
} to anche da exit, vista in uno suddivise in otto lezioni tutto
foreach ($_POST as $ctr) { degli esempi precedenti. quello che bisogna sapere
// foreach ci consente di controllare tutto l'array $_POST per costruire un sito
if (trim($ctr)==""){ Siti di riferimento e imparare il linguaggio
// trim toglie gli spazi vuoti eventualmente presenti in $ctr Se volete avere ulteriori ap- HTML 4.01, i CSS (fogli
die ("<p><h3>Tutti i campi vanno obbligatoriamente compilati</h3>"); profondimenti su PHP potete di stile), Java Script e CGI.
} visitare questi siti: Il corso è completato da utili
} consigli per promuovere
http://www.php.net il proprio sito on line.
http://freephp.html.it
http://www.apache.org
 Invece di usare un form in- Foreach
termedio di passaggio (tra l’al- Foreach, un po' come isset, Se state ricercando un sug-
tro poco elegante, dal momen- ci aiuta a risparmiare tempo gerimento su una qualsiasi fun-
to che il nostro utente potreb- per compiere un'azione di cui zione di PHP, potete accedere
be accedere direttamente alla spesso si ha bisogno: attraver- velocemente alle pagine del
pagina articolo.php una volta sare completamente un array, manuale on-line scrivendo
che ne conosca l'URL), po- effettuando delle operazioni l'URL del sito seguito da uno
tremmo definire dei valori di (assegnazione, confronto, vi- slash con la parola da ricerca-
default validi finché non viene sualizzazione, ...) su un secon- re, ad esempio http://
scelto un diverso carattere dal do array “copia” appositamen- www.php.net/isset (sul manua-
form cliccando su “invia”. te creato. le sarà cercata la parola isset).
Il controllo della definizione La funzione più importante È utile farlo perché, oltre alla
iniziale delle variabili è de- la si rileva quando bisogna descrizione del manuale, si tro-
mandato proprio a isset come operare su un array completo, vano anche molti esempi prati-
esemplificato in articolo- anche solo per visualizzare tut- ci scritti dagli utilizzatori di
due.php (listato 21): ti gli elementi. PHP. 
2a lezione

 A scuola con PC Open

Web Developer PHP di Federico Pozzato

1 Approfondire PHP
ella lezione 1 abbiamo Il discorso sarà poi concluso IL CALENDARIO DELLE LEZIONI
N esplorato le basi di PHP,
dando tutti gli elementi
per creare le nostre prime pa-
nella terza puntata, dove ver-
ranno trattate anche tematiche
relative alla sicurezza e alla ge- Lezione 1: - Proteggere una pagina
gine e alcuni spunti per coglie- stione degli errori. - PHP con un server off line - Cookie e sessioni
re le potenzialità di questo lin- Non parleremo ancora della - Funzioni base e variabili - La funzione mail
guaggio. connessione tra PHP e i data- - I costrutti di controllo
Nella seconda lezione mette- base (con particolare riguardo Le prossime puntate
remo in luce, invece, funziona- a MySQL), in quanto questo ar-  Lezione 2: Lezione 3: PHP e database
lità avanzate che ci consenti- gomento sarà oggetto di tratta- - Approfondiamo PHP Lezione 4: PHP e MySQL
ranno di migliorare i nostri zione specifica e approfondita - Include e require Lezione 5: Gestire un sito
script, rendendoli più efficienti nelle prossime puntate del cor- - Funzioni e classi dinamico con PHP e MySQL
e utilizzabili anche per il futuro. so.

2 Include e require I listati


completi
pesso capita di inserire in dovremo nuovamente armarci unico attributo in un CSS ester- zioni è nella gestio- sono sul CD

S più pagine Web esatta-


mente lo stesso codice: un
esempio tipico sono le righe
di pazienza (molta più di quel-
la che ci era servita quando ab-
biamo realizzato le pagine),
no e il gioco è fatto.
Include e require in PHP
funzionano allo stesso modo
ne degli errori: in
caso di errore, include produce
solo un avvertimento (war-
che formano la testata (hea- aprire tutti i file interessati ed di un CSS esterno: nel punto ning) senza bloccare la pagina,
der) o il piè di pagina (footer), effettuare la modifica. L'opera- voluto del listato Web possia- mentre require blocca la com-
ma possiamo prendere in con- zione può essere più o meno mo inserire una chiamata a un pilazione del linguaggio (fatal
siderazione anche le righe che agevole a seconda del tipo di file esterno il cui contenuto error). Che cosa usare, quindi,
compongono le barre di navi- cambiamento e del software sarà “trasferito” alla pagina è funzione degli obiettivi del
gazione e dei menu, le chiama- utilizzato, e può divenire un chiamante e interpretato dal Webmaster.
te ai database, la protezione di ostacolo insormontabile se i li- parser PHP come appartenen- Un esempio semplice del
pagine con password, la chia- stati delle pagine sono stati te alla pagina di origine. Ogni vantaggio di usare gli inclu-
mata dei CSS esterni e altro an- creati da terzi. Alcuni program- eventuale modifica andrà effet- de/require file lo possiamo ri-
cora. mi, come Home Site, ci vengo- tuata, quindi, solo sul file ester- cavare direttamente dalla quo-
Come agiamo in questi casi? no in aiuto con una utilissima no e automaticamente verrà tidianità. Immaginiamo di aver
Usando il “tradizionale” HTML, funzione che consente di ope- estesa a tutte le pagine interes- creato un sito dove sia neces-
non abbiamo molta scelta: ci rare il replace su più file con- sate. sario inserire in molte pagine
dobbiamo armare di pazienza temporaneamente, però que- PHP ci propone due funzioni un disclaimer a tutela del trat-
ed effettuare una serie di copia- sto non è sufficiente. simili: include e require. Si inse- tamento dei dati personali, co-
incolla di codice su pagine di- Leggendo queste righe im- riscono in maniera estrema- me previsto dalle norme sulla
verse! A parte gli errori sempre maginiamo che qualcuno ab- mente semplice nella pagina privacy. Essendo Webmaster
in agguato nell'operazione del bia pensato ai fogli di stile chiamante, semplicemente in- previdenti abbiamo incluso in
copia-incolla, un grosso pro- (CSS, Cascading Style Sheet) e ai dicando il nome (col percorso ogni pagina interessata (come
blema nascerà con la necessità problemi di modifica del layout relativo) del file voluto: privacy.php, vedi listato_01) un
di modificare una parte qual- di un sito Web. Prima dell'in- <?php file esterno col testo del di-
siasi di questo codice ripetuto: troduzione dei CSS, infatti, mo- include (“testata.inc.php”); sclaimer (disclaimer.inc.php,
prima o dopo, inutile negarlo, dificare gli attributi di struttura ?> vedi listato 2):
avremo bisogno di cambiare (anche solo la dimensione di
qualcosa, vuoi per migliorare una font) su tutte le pagine di <?php <html>
le funzionalità e la navigazione, un sito Web era un lavoro im- require (“testata.inc.php”); <head>
vuoi per aggiornamenti e refre- probo, mentre adesso basta ?> <title>Privacy</title>
sh. Di fronte a questa esigenza semplicemente cambiare un La differenza tra le due fun- </head>
2a lezione

<body> questi file esterni (magari an- 2


<h3>Questa parte di testo è inserita che password), dobbiamo es-
direttamente nella pagina sere sicuri che non siano visi-
privacy.php</h3> bili nel caso qualcuno ci finisca
bla bla bla bla bla bla bla dentro direttamente. Il consi-
<p> glio, quindi, è di nominare que-
<h3>Quella che segue, invece, è sti file inclusi come nomepagi-
inserita nella pagina disclaimer.inc.php na.inc.php, dove il suffisso inc
ed è visualizzata in questa pagina serve a noi per capire al volo
utilizzando un'istruzione include:</h3> che quella pagina è inclusa in
<?php un'altra, mentre l'estensione
Nella pagina accesso.inc sono trasparenti anche i dati riservati
include("disclaimer.inc.php"); php indica al server di trattare
?> la pagina utilizzando il parsing
</body> (è ovvio che nel listato dovran- 3
</html> no essere presenti i tag PHP).
listato 1 Se usassimo solo l'estensio-
ne .inc (o .html o .txt o nessuna)
<em> il browser ci farebbe vedere la
Ai sensi della L. 675/96 ti informiamo pagina come fosse un testo, an-
che tutti i dati in nostro possesso che se contenesse i tag PHP.
verranno utilizzati solo per Buona norma è dunque prova-
pubblicizzare iniziative inerenti XYZWK. re ad aprire direttamente col
Nessun dato verrà ceduto a terzi. In browser tutti i file inclusi e ve-
ogni momento potrai chiedere di dere se è tutto OK per la sicu- La pagina è visibile con fondo verde e non è cliccabile, ma lo sono le altre pagine
essere cancellato dal nostro database rezza dei nostri dati.
con una semplice comunicazione al Se volete una prova del ri-
nostro indirizzo di posta elettronica. schio che si può correre, pro- arg1.php e arg2.php che con- {
</em> vate ad aprire la pagina acces- tengono le sezioni “viaggi e fo- echo "<td ";
listato 2 so.inc: vedrete in maniera del to” e “curriculum”, una pagina if ($chiave==$nome_file) {
tutto trasparente i dati di ac- menu.inc.php (listato_03) per la echo " class='nolink'>".$menu;
Quando il browser chiamerà cesso a un database, password barra di navigazione e un foglio }
privacy.php, l'effetto sarà di ve- compresa (immagine 2). Pro- di stile menu.css per definire else {
dere riportato il testo del di- vate poi a chiamare accesso. l'aspetto della barra stessa. echo " class='link'><a class='nav'
sclaimer come se appartenes- inc.php e vedrete la differenza! La logica da applicare è la se- href='".$chiave."'>$menu</a>";
se alla pagina originale (imma- guente: }
gine 1). Il vantaggio di questa Un esempio pratico • inizializziamo un array as- echo "</td>";
struttura lo avremmo tangibil- Se il primo esempio serviva segnando a ogni nome di pagi- }
mente verificato all'inizio del solo a entrare nell'argomento, na un testo da visualizzare nel- echo "</td><td
2004 quando è entrata in vigore la seconda proposta, invece, la barra che verrà creata; class='lato'>&nbsp;</td></tr></table
la nuova norma di disciplina può trovare utili applicazioni • verifichiamo in quale pagi- >";
del settore (dalla Legge 675/96 pratiche nelle pagine del no- na ci troviamo. Per fare questo ?>
al D.Lgs.196/03): invece di mo- stro sito: useremo include, gli utilizziamo una delle tante va- listato 3
dificare tutte le pagine, l'unica array e i costrutti di controllo riabili superglobals di PHP (in
operazione di modifica l'a- per costruire una barra di na- questo caso $_SERVER[“PHP È chiaro che, se aggiungo al-
vremmo compiuta solo su di- vigazione dinamica. _SELF”] ) in unione con la fun- tre pagine, l'unica operazione
sclaimer.inc.php semplicemen- Lo scopo è sapere sempre in zione basename che restitui- da compiere sarà aggiungere la
te modificando il riferimento quale sezione del sito ci trovia- sce solo il nome del file elimi- nuova pagina all'array $naviga
della Norma (vedi l'esempio mo e dare la possibilità di spo- nando il resto del percorso nel file incluso menu.inc.php.
corrispondente privacy_new. starsi velocemente nelle altre • creiamo una struttura di Il risultato ottenuto (uno dei
php con disclaimer_new.inc. sezioni. La barra verrà inserita controllo di tipo foreach-if: la tanti possibili a seconda di co-
php). come include in tutte le pagine: funzione foreach ci consente di me definiamo il foglio di stile) è
Bisogna porre molta atten- sarà quindi molto flessibile per navigare lungo tutto l'array visibile nell'immagine 3: la pa-
zione al fatto che le pagine cui permettere modifiche future creato, mentre if si occupa di gina dove ci troviamo è visibile
fanno riferimento include e re- nel caso di ampliamento del “distinguere” la pagina attiva con sfondo verde e non è clic-
quire sono a tutti gli effetti pa- progetto. (quella dove ci troviamo) dai cabile, mentre lo sono le altre
gine appartenenti al sito e ri- Per il nostro esempio abbia- link cliccabili. pagine. Fate clic per vedere co-
chiamabili col browser. Se in- mo bisogno di una pagina sa succede entrando nelle altre
seriamo note particolari in main.php, due sottopagine <?php pagine.
// inizializzo l'array La funzione basename con-
1 $naviga = array ("main.php"=>"Home sente anche di estrarre la radi-
page", "arg1.php" => "Viaggi e foto", ce del nome della pagina, eli-
"arg2.php" => "Curriculum"); minando l'estensione. Per fare
questo, l'estensione da elimi-
// verifico in quale pagina mi trovo nare va indicata come secondo
$nome_file = argomento di basename:
basename($_SERVER["PHP_SELF"]);
echo "<table><tr align='center'><td <?php
class='lato'>&nbsp;</td>"; $nome_file =
basename($_SERVER["PHP_SELF"],
// struttura di controllo “php”);
Include e require facilitano l’inserimento dei file di testo uguali in numerose pagine foreach ($naviga as $chiave=>$menu) ?> 
2a lezione

3 Funzioni e classi
pesso si scrivono righe di La funzione deve avere un Una volta scritta, la funzione variabile come fosse la $sconto

S codice uguali per effettua-


re operazioni ripetitive e
comuni a più pagine. Esempi
nome univoco (attenzione: non
possiamo utilizzare i nomi ri-
servati previsti da PHP, come
sarà sempre utilizzabile e non
dovremo neppure preoccupar-
ci di reinterpretare il codice
originale.
Va sottolineato che le varia-
bili usate all'interno della fun-
possono essere gli script per la ad esempio print) e va inserita per adattarlo alle nuove varia- zione non possono essere ri-
creazione di qualche menu, ma (sembra una cosa ovvia, ma bili. Spesso passa molto tempo chiamate all'esterno, quindi
anche listati molto più semplici non sempre è rispettata) in un tra quando si scrive del codice qualsiasi invocazione a $prez-
con i quali si vuole magari cal- punto del listato precedente al- e quando poi lo si riutilizza: an- zo o $sconto nel corso del lista-
colare l'area di un triangolo o la chiamata. Il risultato viene che in questo caso, con le fun- to non produrrà alcun risultato
restituire un valore vero-falso restituito utilizzando l'istruzio- zioni evitiamo di doverci rin- (salvo, ovviamente, non esista-
dopo una verifica. ne return: chiamata all'interno frescare la memoria ricom- no nel corpo della pagina due
Una soluzione semplice e ba- di una funzione, return termina piendo i passaggi logici del pas- variabili con questo nome).
nale può essere usare la classi- immediatamente l'esecuzione sato. Se volessimo questa possi-
ca accoppiata copia-incolla, so- della funzione corrente e resti- Basename è registrata nelle bilità dovremmo definire le va-
luzione valida, però, solo se si tuisce il suo argomento come librerie di PHP ed è valida uni- riabili della funzione come
sa esattamente dove recupera- valore della funzione. Possia- versalmente per tutti gli utiliz- $GLOBALS (col loro nome) al-
re il codice da copiare. Potrem- mo inserire più istruzioni re- zatori. Nel nostro piccolo, l'interno dello script della fun-
mo riuscire a risolvere veloce- turn all'interno della stessa fun- però, anche noi abbiamo biso- zione stessa. L'esempio è ri-
mente il nostro problema, zione, tenendo presente che, gno di semplificarci la vita e portato nella pagina sconto_
aprendo comunque la strada a appena incontrato il return, il quindi decidiamo di scrivere la global.php dove, all'interno del-
possibili errori: copiatura erra- codice proseguirà al di fuori nostra prima funzione (listato la dichiarazione della funzione
ta del codice, difficoltà ad adat- della funzione. 4) per calcolare il prezzo netto prezzo_netto è presente l'istru-
tare il nome delle variabili con Finora abbiamo visto moltis- di un bene, dato uno sconto zione:
possibili dimenticanze sempre sime funzioni predefinite di espresso come valore da 0 a
in agguato, propagazione di PHP: basename, ad esempio, è 100: $GLOBALS[“sconto”] = $sconto;
eventuali errori contenuti nelle una di queste. Basename, infat-
righe originali, difficoltà nell'in- ti, necessita di alcuni argomen- function prezzo_netto($prezzo, Adesso sarà possibile chia-
dividuazione del codice che ti (il percorso della pagina e $sconto) mare la variabile $sconto anche
potrebbe essere diversamente un'eventuale estensione) e re- { all'esterno della funzione, men-
incapsulato nelle pagine. stituisce di conseguenza il va- if ($sconto<0 or $sconto>100) { tre non si potrà chiamare
Per venire incontro alle esi- lore atteso, ossia il nome della return “Questa funzione assume che lo $prezzo perché non è stata di-
genze dei Webmaster, PHP ci pagina con o senza estensione. sconto debba essere un numero chiarata globale.
aiuta con funzioni e classi. Una funzione può restituire compreso tra 0 e 100, mentre tu hai Possiamo definire anche
anche solo un valore vero-falso inserito uno sconto uguale a $sconto”; fUnzioni senza argomenti: è il
Le funzioni (true-false), da usare magari in } caso delle funzioni che effet-
Le funzioni sono script di combinazione con un if per $netto=$prezzo*(1-$sconto/100); tuano dei controlli ripetitivi e
codice da invocare e da cui ci si creare un ciclo di controllo, o return $netto; restituiscono una stringa o dei
attende una risposta: un qualsiasi altro tipo di varia- } valori true/false.
bile (valori, array, oggetti). listato 4 La funzione controllo(), pro-
function esempio (eventuali Usare le funzioni consente di posta come esempio, verifica
argomenti) concentrarsi sul codice puro Questa funzione può essere per prima cosa se esiste una
{ (“astratto”) della funzione, sen- usata dovunque ce ne sia biso- cartella varie posta allo stesso
codice za doversi preoccupare del si- gno: l'applicazione pratica la si livello della pagina Web su cui
return risultato restituito gnificato delle variabili all'e- vede nella pagina sconto.php viene inserita. Se la cartella esi-
} sterno della funzione stessa. che contiene un form con due ste, viene poi verificato se è
campi dove inserire i valori di vuota o se contiene dei file. La
4 prezzo e sconto sulla base dei logica che sta alla base della
Nome cartella quali calcolare il prezzo netto. funzione è esprimibile in forma
Da notare è la chiamata della di algoritmo, come si può ve-
funzione prezzo_netto nella pa- dere nell'illustrazione 4. Per
gina sconto.php: funzioni semplici, disegnare un
algoritmo può essere solo una
No echo “Prezzo netto: ”.prezzo_netto perdita di tempo, ma è essen-
Esiste? RETURN 1
($_POST['pre'],$_POST['sco']); ziale per funzioni più comples-
se ed è quindi buona abitudine
Sì Come si vede, le variabili imparare a usarli.
passate come argomento della La funzione è riportata nel li-
No funzione hanno un nome diver- stato 5, mentre la pagina Web di
Contiene file? RETURN 2
so da quello assegnato nello esempio è la checkvarie.php.
script della funzione, ma la co- Provate a creare e cancellare la
Sì sa non ha la minima importan- cartella varie, lasciandola vuo-
za perché questo è il senso del- ta o inserendo qualche file.
RETURN 3 le funzioni: PHP, infatti, inter-
preta la prima variabile passa- function controllo()
ta come fosse la variabile // questa funzione controlla che in
Un algoritmo esprime la logica che sta alla base della funzione controllo () $prezzo originale e la seconda una directory predefinita sia presente
2a lezione

almeno un file (ed elegante) consiste, invece, proprietà. Lo faccio senza pen- bo colorato. A questo punto
{ nello salvare le funzioni in file sare all'oggetto specifico X o al- per risolvere il nostro compito
$cartella=@opendir('varie'); separati includendoli poi co- l'oggetto specifico Y, bensì non ci resta che creare due “og-
if (!$cartella) { me già visto. Ogni modifica fat- guardando al concetto più getti” facenti riferimento a que-
return "Attenzione: è inutile cercare ta sulla funzione verrà quindi astratto possibile grazie al qua- sta classe, inizializzando sem-
file... la cartella non esiste e quindi propagata automaticamente a le posso poi definire gli oggetti plicemente i due oggetti con le
devi prima crearla"; tutte le pagine: specifici. loro caratteristiche. Siamo in
} Una classe è, quindi, una col- grado di creare infiniti rombi e,
while (false !== ($file = <?php lezione di variabili (proprietà) fondamentale, siamo in grado
readdir($cartella))) { include (“funzione_controllo.inc.php”); e funzioni (metodi) che utiliz- di farlo pur non sapendo nulla
$lista[]=$file; ?> zano queste variabili: di cosa sia un rombo! Forniti i
} dati di colore e dimensioni, in-
$fine=count($lista)-2; Non è possibile, per chiarez- class Nuova_classe fatti, è la classe che si incarica
if ($fine==0){ za di comportamento del codi- { di restituire gli oggetti in ma-
return "Attenzione: Non ci sono file ce, ridefinire funzioni già di- variabili (proprietà) niera del tutto trasparente per
nella cartella"; chiarate all'interno di uno stes- funzioni (metodi) l'utente.
} so listato (overloading). } Vediamo di fare un esempio
return “Prosegui pure: nella cartella di programmazione di classe:
c'è almeno un file”; Le classi Definita una classe come ve- supponiamo di creare una clas-
} Le funzioni sono costrutti dremo in seguito, possiamo ge- se Quadrato grazie alla quale,
listato 5 semplici, adatti a lavori ripeti- nerare un oggetto utilizzando il una volta definito il lato, pos-
tivi da cui ci si aspetta un unico costrutto new: sano essere ricavati i valori di
Per rendere più utilizzabile risultato. area, perimetro e diagonale. La
questa funzione, si può passare Non sempre ciò è sufficiente, $oggetto = new Nuova_classe; definizione completa della clas-
alla funzione un argomento basti pensare al caso di costru- se la trovate in classe_quadra-
uguale al percorso della cartella zioni di codice avanzato in gra- È il codice della classe che to.inc.php, mentre qui ci basta
da controllare. La modifica è fa- do di interagire con altre fun- “definisce” l'oggetto, il quale un estratto (listato_06) con so-
cile (la trovate in checkvarie_ zioni e variabili: un esempio deve essere creato, tramite l'i- lo il metodo “area”.
plus.php): basta definire la fun- può essere la creazione di un struzione new, con un nome
zione controllo ($directory) e sistema di gestione avanzato di diverso da quello di altri ogget- class quadrato
inserire $directory all'interno commercio elettronico, magari ti istanziati (cioè inizializzati) {
della funzione come argomen- da esportare su più siti. In que- dalla stessa classe. Per il con- // dichiarazione delle variabili
to di opendir. sto caso un'architettura de- cetto stesso che sta alla base utilizzate (da accompagnare con una
Ulteriore esercizio è prende- mandata a funzioni stand-alone della programmazione OO, in- descrizione, per rendere più leggibile il
re il percorso della cartella da è possibile, ma diventa sempre fatti, è possibile definire quanti codice)
controllare direttamente da un più difficile da gestire all'au- oggetti si vuole basandoli su var $lat;
form: provate a costruire la pa- mentare della complessità ri- una stessa classe. Ricordate la var $ar;
gina da soli e poi confrontatela chiesta. scorsa puntata quando parla- var $per;
con checkvarie_form.php (vedi Per esigenze di questo tipo vamo dei tipi di variabili? Man- var $diago;
immagine 5). Adesso potete ci viene in aiuto il concetto di cava solo il tipo object, ossia
controllare tutte le cartelle che classe, grazie al quale potremo proprio quello definito usando function quadrato($lato)
volete, l'unica accortezza è ri- addentrarci brevemente nella la classe. // costruttore
cordarsi che il percorso della programmazione rivolta agli Definito un oggetto, a esso è {
cartella è relativo e non assolu- oggetti. La trattazione non può possibile applicare tutti i me- $this->lat=$lato;
to. essere esaustiva perché l'argo- todi implementati nella classe }
Abbiamo detto all'inizio del mento prevede conoscenze di appartenenza, in maniera
paragrafo che la funzione origi- specialistiche, ma la cosa im- molto semplice e con una puli- function area()
nale deve essere presente nel portante è riuscire a cogliere il zia di codice inarrivabile per // calcola l'area del quadrato
codice prima di un’eventuale concetto alla base della pro- una programmazione stan- {
chiamata. Potremmo pensare grammazione OO (Object dard. $this->ar=$this->lat*$this->lat;
di inserire (copia-incolla) la Oriented) per poterlo poi ap- Facciamo un esempio tratto return $this->ar;
funzione in tutte le pagine che profondire con testi o corsi dalla vita di tutti i giorni: se de- }
ci interessano, ed è una valida specifici. vo disegnare un rombo grande }
idea se le pagine che usano Orientarsi agli oggetti signi- rosso e un rombo piccolo gial- listato 6
questa funzione sono poche, fica porre l'accento sulla defi- lo, sostanzialmente devo fare
altrimenti ricadiamo nei pro- nizione di tutte le proprietà ge- due operazioni simili. Ci sono due cose da notare:
blemi già descritti in preceden- neriche di un certo oggetto e Qual è la differenza tra i due quando è definita una funzione
za. Una soluzione più efficiente delle funzioni legate a queste “oggetti” da disegnare? Solo la con lo stesso nome della clas-
dimensione e il colore, dal mo- se, questa funzione prende il
5 mento che la definizione di nome di costruttore. Il costrut-
rombo è unica! Bene, allora è tore è utile in certe classi per-
sufficiente che sia dichiarata ché inizializza il tipo di oggetto
(una volta per tutte) una “clas- della classe stessa. In questo
se” Rombo all'interno della caso il costruttore serve a ini-
quale siano introdotte le varia- zializzare l'oggetto col valore
bili dimensioni e colore che del lato del quadrato. Il co-
consentono di effettuare il di- struttore può anche non essere
segno. indicato, ma se lo è sarà inter-
Alla classe non interessa il ti- no alla classe e avrà necessa-
po di rombo da disegnare, ma riamente il nome della classe
Il risultato in pagina della funzione controllo solo definire che cos'è un rom- stessa. 
2a lezione

 La seconda notazione im- quadrato($a); // per chiamare la funzione drato_1 e $nuovo_quadrato_2):


portante è il modo di passare il “diagonale” e per ritornare il valore le chiamate a variabili e funzio-
nome delle variabili all'interno Creato l'oggetto $nuovo_ della diagonale ni differiscono solo ed esclusi-
della classe: abbiamo detto che quadrato_1, per chiamare le echo "Diagonale: vamente per il nome dell'og-
ogni classe può creare N ogget- funzioni o le variabili useremo ".$nuovo_quadrato_1- getto, e ci consentono di otte-
ti basati su di essa, ma sempre la notazione che già conoscia- >diagonale()."<p></h5>"; nere facilmente tutti i dati utili
con nome diverso. Non poten- mo (->), ricordandoci di indica- listato 7 di un “oggetto” quadrato.
do a priori conoscere il nome re sempre il nome dell'oggetto Lasciamo per ultima una
dell'oggetto, all'interno della appena creato (vedi listato 7): Questo esempio di classe è considerazione ormai ovvia: la
classe dovremo usare il co- banale, ma permette di coglie- classe va naturalmente “inclu-
strutto $this-> generico: // creo un nuovo oggetto della classe re l'essenza della programma- sa” nella pagina chiamante e
quadrato con lato 5 zione OO: definite proprietà e posta prima della creazione di
$this->nome_variabile $a=5; metodi di una classe sarà pos- qualsiasi oggetto.
echo "<h3>Quadrato_1:<p></h3>"; sibile, infatti, creare e gestire Una classe può essere an-
In questo modo tutte le va- $nuovo_quadrato_1=new oggetti in maniera semplice e che la base di un'altra classe
riabili definite nella classe sa- quadrato($a); senza preoccuparsi di tutto che ne estende le funzionalità.
ranno disponibili per ogni og- quello che c'è nella classe. In questo caso nella seconda
getto creato in seguito. echo "<h5>Lato: Con una ricerca su Internet classe indicheremo solo il co-
Un esempio completo è ri- ".$nuovo_quadrato_1->lat."<p>"; si trovano numerose classi dice nuovo senza doverci
portato nella pagina classe.php, // per chiamare la funzione “area” e pronte da usare. Una, ad esem- preoccupare di funzioni e va-
dove possiamo vedere come per ritornare il valore dell'area: pio, serve a superare il limite riabili già costruite nella prima
inizializzare gli oggetti e come echo "Area: ".$nuovo_quadrato_1- del timestamp: non occorre ca- classe. Il costrutto da cercare
chiamare variabili e funzioni. >area()."<p>"; pire cosa c'è sotto, ma solo sa- nel manuale di php.net è ex-
Un oggetto va istanziato (ini- // per chiamare la funzione pere come istanziare l'oggetto tends:
zializzato) usando il costrutto “perimetro” e per ritornare il valore del e quali funzioni chiamare.
new: perimetro: In classe.php abbiamo inseri- class quadrato_plus extends quadrato
echo "Perimetro: to due oggetti diversi (due qua- {
$a=5; ".$nuovo_quadrato_1- drati di lato diverso) basati sul- codice
$nuovo_quadrato_1=new >perimetro()."<p>"; la stessa classe ($nuovo_ qua- }

4 Proteggere una pagina con password


on la definizione di fun- re l'accesso a una pagina. Ve- menti ci troveremo di nuovo di

C
<input type="submit" name="invio"
zioni e classi abbiamo diamo adesso un paio di esem- fronte al form vuoto. value="Connetti">
esaurito le nozioni fonda- pi, rimandando poi l'approfon- </form>
mentali di PHP. dimento del discorso a dopo <?php <?php
Arrivati a questo punto non l'introduzione dei database (le- }
dovrebbe quindi essere un pro- zione 4). function controllo ($confronto, $pass) { else {
blema affrontare un compito PHP ci consente di ottenere if ($confronto==$pass) { // la password è esatta e quindi
molto pratico (e utile), ossia la protezione di una pagina in return true; posso avere accesso alla pagina
elaborare qualche strategia per molti modi. Quello scelto per } echo "<h3>Hai inserito la password
proteggere una o più pagine esercizio implica la creazione return false; giusta. La pagina è a tua
del nostro sito Web da occhi in- di una funzione e l'uso di un ci- } disposizione</h3>";
discreti. In pratica, vogliamo clo di controllo (listato_08). La }
che a certe pagine possano pagina di esempio è protet- $password=”pluto”; ?>
avere accesso solo le persone ta_1.php, e al primo accesso ci // la password “pluto” l'abbiamo listato 8
dotate di una password, o me- fa vedere un form dove l'unico impostata noi
glio di una precisa accoppiata campo da compilare è quello Una variazione sullo stesso
username-password. relativo alla password da inse- $check=controllo($_POST['pwd'], tema (meno elegante, ma
I motivi di questa decisione rire. $password); ugualmente efficace) la potete
possono essere i più vari: su La funzione controllo si oc- // $check assumerà valore true o vedere in protetta_1_var.php.
una pagina possiamo avere in- cupa solo di restituire un valo- false in dipendenza del valore inserito Per migliorare la costruzio-
serito testi e immagini che solo re true o false, a seconda che il nel form ne presentata, bisogna quanto-
i nostri amici più cari devono confronto tra le due variabili meno posizionare in un file
leggere, ma potrebbe anche es- dia esito positivo o negativo. if ($check==false) { esterno la funzione e il valore
sere una esigenza di lavoro che Nel nostro caso, il valore resti- // la password è errata o non è mai assegnato da noi alla password
ci impone di tutelare certe tuito dalla funzione sarà asse- stata inserita (vedere password.inc.php e pro-
informazioni, oppure una parte gnato a una variabile $check, la ?> tetta_1_inc.php).
del Web site deve essere pro- quale chiama la funzione usan- <h3>Inserisci la password corretta per In questo modo è possibile
tetta perché da essa è possibi- do come campi la password in- entrare nella pagina protetta</h3> usare il costrutto include per
le gestire gli aggiornamenti del serita nel form e la password <form action="protetta_1.php" inserire senza errori la stessa
sito stesso. definita da noi (pluto). Se method="post"> password in più pagine e se si
Qualunque sia il motivo, ab- $check avrà valore true allora la <input type="password" modifica la password lo si fa in
biamo la necessità di protegge- pagina sarà visualizzata, altri- name="pwd"> = password<p></p> un unico punto.
2a lezione

Un altro limite, però, è pro- il codice precedente, introdu- } sulla pagina protetta_2.php.
prio quello di avere una sola cendo un controllo username- } Adesso siamo in grado di mo-
password per tutte le persone password. return false; dificare username e password
che hanno accesso alle pagine: Usiamo la stessa logica vista } delle singole coppie.
se dovessimo cambiarla per nel primo esempio, con la no- Anche in questo caso, poi,
motivi di sicurezza (poniamo vità di creare un array conte- // valori di username e password sarà buona consuetudine por-
che sbadatamente qualcuno nente le coppie username-pas- decisi da noi tare in un file esterno la funzio-
abbia comunicato la password sword. $coppie=array("pippo"=>"pluto", ne e la definizione di $coppie
a persone non autorizzate) do- La parte di codice che ci in- "topolino"=>"minni", (vedi pagine password_2.inc.
vremo informare necessaria- teressa (con la nuova funzione "paperino"=>"paperina"); php e protetta_2_inc.php).
mente tutti gli attori coinvolti. di confronto e con l'array $cop- Nel prosieguo del corso ve-
Sarebbe invece più efficiente pie) è visibile in listato_09: // $check darà un valore true o false dremo come usare i database
assegnare a ogni persona una $check=controllo_coppia($coppie,$_ per proteggere una pagina e
diversa coppia username-pas- function controllo_coppia($confronto, POST['user'],$_POST['pwd']); come evitare di dover inserire
sword, in modo da modificare, $user,$pass) { listato_09 username e password su ogni
eventualmente, soltanto la pas- foreach ($confronto as $chiave=>$val) pagina protetta.
sword di quella persona speci- { La parte che segue il listato 9 Ma per questi argomenti
fica. if ($chiave==$user and $val==$pass) { è uguale a quanto già visto e l'e- l’appuntamento è alle lezioni 4
Vediamo allora di modificare return true; sempio completo è riportato e 5.

5 Cookie e sessioni
l protocollo HTTP è un proto- prima di cookie e poi introdur- dal disco fisso del client. Se il valido sei mesi.

I collo stateless, cioè non di-


spone di un metodo per man-
tenere una memoria relativa al-
remo il concetto di sessione,
assolutamente da conoscere
sia per trasmettere dati all'in-
nostro scopo è usare i cookie
per recuperare i dati di accessi
effettuati in momenti diversi,
La prima parte da esaminare
(listato 10) è il codice che pre-
cede l'inserimento del tag
lo stato della comunicazione terno del proprio Web domain dovremo quindi assegnare una <html>. Con setcookie inizializ-
tra client e server. Per ovviare a che per superare, in alcuni ca- durata (un minuto, un giorno, ziamo per la prima volta (o ag-
questa mancanza vengono in si, il problema della disabilita- un mese, un anno...) al “biscot- giorniamo se già esisteva) un
nostro aiuto i cookie e le ses- zione dei cookie. tino”. cookie di nome data: esso con-
sioni. Le istruzioni che coinvolgo- tiene il valore $data che indica
Sappiamo tutti bene cosa Cookie no i cookie vengono inviate in- quando la pagina è stata vista
siano i cookie: piccoli file regi- Poniamo di volere inizializ- sieme con gli header HTTP (gli l'ultima volta. La durata del
strati sul nostro PC (lato client) zare un cookie in modo da ri- header sono le righe di intesta- cookie è espressa in secondi a
e richiamati dalla pagina Web conoscere un utente che abbia zione HTTP che indicano al partire da oggi, quindi usiamo
caricata (lato server). Lo scopo già visitato il nostro sito. Ma- browser come comportarsi) e la funzione time() aggiungendo
è recuperare informazioni pre- gari potremmo avergli chiesto vanno pertanto chiamate (pe- il numero di secondi per arri-
cedentemente fornite dall'u- nelle precedenti visite quale se- culiarità degli header) prima di vare a sei mesi circa.
tente in maniera più o meno zione preferisce, in modo da in- qualsiasi output di pagina os-
trasparente. Se usati coscien- dirizzarlo direttamente verso sia prima anche del tag <html>. <?php
ziosamente dai Webmaster, i quella specifica pagina. Un'altra importante peculia- $data = date("d-m-y")." alle ore
cookie si dimostrano indubbia- PHP imposta i cookie con la rità da ricordare è che, aperta ".date("H-i-s");
mente utili quando richiamano funzione setcookie: una pagina, viene sempre recu- setcookie("data", $data,
dati che altrimenti dovremmo perato il valore del cookie time()+15800000);
ogni volta settare, però al con- setcookie (nome, valore, durata) eventualmente registrato in ?>
tempo possono dimostrarsi de- // valore e durata sono parametri precedenza: l'aggiornamento listato_10
leteri se servono, come avvie- opzionali del cookie (o la sua registrazio-
ne col “cavallo di troia”, per ne) verrà letto solo quando la Il codice del listato 11, inve-
estrarre dal PC informazioni e registra i valori nella varia- pagina sarà ricaricata succes- ce, è contenuto tra i tag <html>
inerenti la nostra privacy e re- bile globale $_COOKIE (ricor- sivamente. Questo ci facilita dell'esempio proposto. Il ciclo
lative a siti da noi visitati, scel- date le variabili globali? Ne ab- nella scrittura del codice dei if controlla se il cookie data esi-
te effettuate o simili. biamo parlato nella scorsa nostri listati. ste: in caso positivo ci dice
Proprio a causa della pessi- puntata) così da poterla richia- Un esempio è più chiaro di quando abbiamo visto la pagi-
ma pubblicità fatta ai cookie, mare in un secondo momento. tante parole (vedi cookie.php): na l'ultima volta, in caso nega-
molti utenti ne disabilitano Il nome del cookie è sempre supponiamo di voler accoglie- tivo ci informa che è la prima
completamente la registrazio- obbligatorio, mentre non lo so- re un navigatore che torna nel volta che accediamo al sito.
ne nel proprio PC, o quanto- no né il valore né la durata. nostro sito indicandogli quan- Ricordiamo che la lettura del
meno la abilitano solo per siti Lasciando vuoto il campo do ci ha visitati l'ultima volta. cookie si riferisce sempre allo
assolutamente fidati. valore, il cookie specificato Per fare questo dobbiamo in- stato precedente a quello even-
Assumendo di utilizzare i verrà inizializzato assegnando- nanzi tutto verificare se il navi- tualmente settato sulla pagina
cookie in senso positivo, do- gli un valore null. Anche la du- gatore possiede un nostro aperta.
vremo tenere conto di queste rata è opzionale. Se non viene cookie precedentemente regi-
possibili limitazioni e agire di indicato nulla, il cookie sarà at- strato, altrimenti dobbiamo <?php
conseguenza. tivo solo fino alla chiusura del creare il cookie per la prima if (isset($_COOKIE['data'])) {
In questa sezione parleremo browser e poi verrà cancellato volta. Il cookie dovrà essere echo "<h4>Ciao amico, hai già visitato 
2a lezione

 queste pagine. L'ultima volta che hai ne passato attraverso un sione solo dati che possano, tutto cancellata con l'istruzio-
aperto questa pagina è stato il cookie temporaneo che viene nel caso più malaugurato, es- ne session_destroy.
".$_COOKIE['data']."</h4>"; poi cancellato dal client quan- sere letti da altri senza danni.
} do viene chiuso il browser (o Giusto per fare un esempio, Il carrello della spesa
else { quando la sessione è esplicita- se si vuole usare la sessione E ora vediamo un esempio
echo "<h4>Ciao amico, è la prima mente chiusa con un'operazio- per mantenere attivo, durante pratico che può dare molti
volta che visualizzi questa pagina ne di logout). Da parte del un collegamento, l'accesso a spunti: il carrello della spesa.
oppure hai cancellato il cookie dalla Webmaster non c'è da fare nul- più pagine riservate, è bene Supponiamo di avere una pagi-
memoria del tuo PC</h4>"; la di particolare. non salvare come variabile di na all'interno della quale sia
} Il secondo sistema, invece, sessione un dato sensibile co- possibile scegliere tra libri e di-
?> consiste nel passare il SID at- me la password. In ogni caso, schi da due elenchi (vedi la pa-
listato 11 traverso l'URL di una pagina niente allarmismi: ricordo che gina lista.php), e una pagina
usando i metodi GET o POST, il SID identificante la sessione che funga da riepilogo (vedi
Un cookie può essere can- quindi ogni link di pagina sarà è composto da 32 caratteri al- carrello.php) di quanto scelto
cellato assegnandogli un valo- del tipo: fanumerici casuali ed è quindi durante la sessione in corso,
re null in questo modo: estremamente improbabile potendo anche tornare in un
<a href=”nuova pagina.php?<?php che un estraneo possa entrare secondo momento nella lista
setcookie (“data”); echo SID; ?>">Clicca qui</a> accidentalmente in una nostra per ordinare altri prodotti.
sessione! Sulla pagina lista.php va no-
Sessioni Quale scegliere? Il metodo Per usare le sessioni, le re- tata la chiamata della sessione
I cookie, lo abbiamo appena “cookie” è più semplice dal gole da conoscere sono relati- e la trasmissione del SID all'in-
visto, salvano un piccolo file di momento che non bisogna fare vamente poche. terno della riga di intestazione
informazioni all'interno del no- nulla, però dovremo preoccu- Innanzi tutto, quando un vi- del form. In questo modo non
stro PC, quindi lato client. Le parci di prevedere la trasmis- sitatore accede al sito, PHP ci interessa sapere se un uten-
sessioni, al contrario, sono un sione del SID anche per quegli controllerà (su nostra esplicita te abbia o meno i cookie atti-
metodo lato server per archi- utenti che hanno disabilitato i richiesta formulata tramite la vati:
viare informazioni relative a un cookie, quindi o si fa un con- funzione session_start) se uno
singolo accesso. trollo per vedere se i cookie di specifico ID di sessione sia pre- <form action='carrello.php?<?php
Per avere un esempio, pos- sessione sono attivi (basta ve- sente. echo SID; ?>' method="post">
siamo pensare ai siti di com- rificare se esiste un cookie In caso positivo il preceden-
mercio elettronico in cui è pre- chiamato PHPSESSID) o si tra- te ambiente salvato verrà ri- Fatta la selezione e fatto clic
sente un “carrello della spe- smette sempre e comunque il creato, altrimenti verrà inizia- sul pulsante Vai ci troviamo
sa”: il compito essenziale per il SID. lizzata una nuova sessione col nella pagina carrello.php dove
Webmaster è mantenere regi- In realtà esiste anche un ter- suo specifico SID. si vedono le selezioni effettua-
strate le scelte effettuate da zo metodo di passaggio del Come visto per i cookie, an- te fino a quel momento. Ciò è
un cliente durante un collega- SID, completamente traspa- che session_start() dovrà esse- reso possibile dalle variabili di
mento (l'utente potrebbe ac- rente per programmatore e re chiamata prima di qualsiasi sessione, come si può vedere
quistare N libri, spostandosi utente dal momento che il SID output html. Le variabili di ses- analizzando l'estratto visibile
continuamente di pagina in pa- è trasmesso automaticamente. sione saranno poi richiamate nel listato 12.
gina). La sessione serve pro- Questa possibilità, però, impli- come variabili globali $_SES-
prio a questo, a mantenere me- ca l'attivazione dell'opzione SION, e potranno essere “can- <?php
moria delle scelte fatte duran- trans_sid nel php.ini, cosa non cellate” in maniera molto sem- session_start();
te un collegamento da ogni sin- sempre possibile se il server plice usando l'istruzione unset. // controllo se è stato selezionato un
gola persona, scelte che poi non è nostro. Inoltre general- La sessione può essere del libro
possono essere memorizzate o mente l'opzione è disattivata
cancellate! Si potrebbero an- di default e quindi non tratte- 6
che usare i cookie, ma in que- remo questo caso.
sto caso ci sarebbe il problema Cosa succede dei file sessio-
di cosa fare se sono stati disa- ne registrati sul server? Quan-
bilitati. to tempo restano salvati? La
Con le sessioni, i dati sono durata di salvataggio dei dati
registrati nel server che ospita sul server e anche la durata
il sito e vengono identificati (e della sessione stessa sono de-
differenziati gli uni dagli altri) finite nel php.ini e quindi di-
tramite un identificativo uni- pendono dal gestore del ser-
voco denominato SID (Session ver: questi valori sono visibili
Identifier). Il SID (casuale e non visualizzando la pagina ph-
prevedibile: è formato da 32 pinfo di cui abbiamo parlato
caratteri alfanumerici) viene nella prima lezione.
assegnato a ogni utente che si È chiaro, altresì, che un file
collega al sito e la sessione vie- di sessione potrà essere recu-
ne mantenuta attiva (ossia vie- perato e riutilizzato in un se-
ne mantenuto lo “stato”) fin- condo momento solo se si è te-
ché il SID viene passato tra nuta nota del SID, altrimenti
server e client durante la navi- non vi si potrà accedere in nes-
gazione del sito. sun caso.
Fondamentale, dunque, è il Va posto un minimo di at-
passaggio del SID, operazione tenzione al fatto che i file sal-
che può avvenire in due modi. vati sul server sono semplici fi-
Nel primo caso tornano utili i le di testo non criptati: è bene,
cookie: se sono attivi, il SID vie- quindi, salvare nei file di ses- La pagina carrello.php presenta le selezioni effettuate dall’utente
2a lezione

if ($_POST['libro']) { ste, per gestire mailing, per // soggetto della mail


header("Location: lista.php");. spedire cartoline elettroniche $subject=stripslashes($_POST['
//controllo se il libro selezionato e chi più ne ha più ne metta. soggetto']);
esiste già nel carrello Provate ad attivare e disatti- La funzione preposta a tutti
if (isset($_SESSION['libro'][$_POST[' vare i cookie dal vostro PC per questi usi ha una forma estre- // oggetto della mail. In questo punto
libro']])) { verificare il funzionamento del- mamente semplice e compat- il costrutto “\n” serve a far andare il
$_SESSION['libro'][$_POST['libro']]++; le sessioni. Un'altra annotazio- ta: testo a caporiga nella mail che ci
} ne che può essere utile: di de- arriverà al nostro indirizzo
else { fault il nome della sessione è mail (destinatario, oggetto, messaggio, $object=stripslashes($_POST['nome'])
$_SESSION['libro'][$_POST['libro']]=1; PHPSESSID, quindi per stam- header e messaggi addizionali) ."\n\n";
} pare le 32 cifre identificative // il quarto campo è opzionale e può $object.="Oggetto:
} basta chiamare: contenere tutti i vari header che ".stripslashes($_POST['testo']);
listato 12 vediamo analizzando il codice sorgente
echo $PHPSESSID; di una mail // mittente della mail
Per prima cosa si verifica $from="From:".$_POST['email'];
che un libro sia stato effettiva- Se volessimo recuperare Con questa funzione possia-
mente selezionato, quindi vie- una vecchia sessione (cono- mo simulare in tutto e per tut- // funzione che spedisce la mail
ne creato (o modificato au- scendo il PHPSESSID), basta to quello che facciamo col no- mail($to,$subject,$object,$from);
mentando la quantità di 1) il scrivere l'URL della pagina car- stro programma di posta elet- ?>
vettore $_SESSION['libro'] che rello in questo modo: tronica, quindi possiamo spe- listato_13
ha una struttura del tipo: dire mail di solo testo o con
http://mio.sito/carrello.php?PHPSESS HTML, aggiungere allegati, in-
$_SESSION['libro'] [libro selezionato] = ID= serire immagini in linea, spedi- Anche eventuali campi da
quantità xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx re la mail a destinatari in CC inserire in copia o copia na-
(carbon copy) o BCC (blank scosta vanno inseriti nel quar-
Stessa operazione viene fat- Adesso che questo semplice carbon copy). to campo di mail(), separan-
ta per il vettore $_SESSION['di- carrello della spesa è comple- In realtà proprio la compat- doli con i caratteri speciali
sco'], quindi i due vettori ven- to, magari potremmo voler tezza della funzione rende al- \r\n che determinano le azioni
gono stampati col classico ci- spedire l'ordine direttamente cune delle operazioni sopra di “ritorno carrello” e “a capo”.
clo foreach (dopo averli ordi- via e-mail. Vediamo come fare descritte alquanto complicate Un esempio è presente nel li-
nati usando l'istruzione ksort). questa operazione. visto che bisogna conoscere stato 14:
Il risultato è visibile nell'imma- la codifica MIME di spedizione
gine 6. La funzione mail delle mail. Fortunatamente in <?php
Per aggiungere altri prodotti Attenzione: per verificare il Internet si trovano classi già $to="mioindirizzo@miosito.it";
basta fare clic sul link di fondo funzionamento off-line della pronte all'uso per risolvere $subject=stripslashes($_POST['
pagina che ci riporta alla lista funzione mail sul vostro PC de- questi problemi. soggetto']);
di selezione, mantenendo me- ve essere installato anche un Qui impareremo le nozioni $object=stripslashes($_POST['nome'])
moria dell'identificativo della server mail. Poiché questo fondamentali su come spedire ."\n\n";
sessione ed eventualmente tra- esula dalla presente trattazio- un’e-mail in formato testo. Il $object.="Oggetto:
smettendoli. ne, il consiglio è di verificare le caso tipico è quello della spe- ".stripslashes($_POST['testo']);
Il link che consente di can- pagine descritte caricandole dizione di un’e-mail a seguito
cellare la sezione ci fa passare su uno spazio Web on-line do- della compilazione di un form // inseriamo il mittente nel quarto
attraverso la pagina logout. ve PHP sia attivato. predisposto su Internet (vedi campo della funzione
php, che serve unicamente a PHP comprende una funzio- form_posta.php). Il form con- $intestazioni="From:".$_POST['email']
eliminare tutti i dati della ses- ne mail, fondamentale per po- tiene solo quattro campi da .”\r\n”;
sione e a reindirizzarci nuova- ter creare form attraverso i compilare: nome e indirizzo di
mente alla lista di partenza quali gli utenti possano scri- posta del mittente, soggetto e // aggiungiamo una coppia di mail
con l'istruzione: verci, per automatizzare rispo- corpo della mail stessa (imma- ($cc_1 e $cc_2) in copia
gine 7). Cliccando su Spedisci $intestazioni.="Cc:".$cc_1.”,
7 si apre una seconda finestra “.$cc_2.”\r\n”;
che ci conferma l'avvenuta
spedizione della mail. // aggiungiamo una mail ($bcc_1) in
Nel codice di questa pagina copia nascosta
(spedisci.php) inseriamo il no- $intestazioni.="Bcc:".$bcc_1.”\r\n”;
stro indirizzo (destinatario) e
la funzione mail (listato 13). // funzione che spedisce la mail
Notiamo che il mittente va in- mail($to,$subject,$object,$intestazioni
serito usando un'istruzione );
From posta nel quarto campo ?>
della funzione mail (il campo listato 14
addizionale). La funzione stri-
pslashes serve a evitare pro- Per rendere più efficace la
blemi nel caso in cui chi com- funzione mail() si può pensare
pilasse il form usasse caratteri di inserire nella pagina spedi-
particolari come le virgolette, sci.php una serie di controlli
gli apici, le slash. per evitare che si possano la-
sciare campi vuoti nel form, e
<?php per verificare il corretto inseri-
// destinatario della mail mento dell'indirizzo mail del
$to="mioindirizzo@miosito.it"; mittente. 
I quattro campi da compilare del form_posta.php
3a lezione

 A scuola con PC Open

Web Developer PHP di Federico Pozzato

1 PHP e i database
a terza puntata del corso è concetti fondamentali riguar-
IL CALENDARIO DELLE LEZIONI
L divisa concettualmente in
due sezioni ed è il trâit d'u-
nion tra i due oggetti di questa
danti i database, concetti sen-
za i quali non saremo in grado
di sfruttarne al meglio le carat-
Lezione 1:
- PHP con un server off line
- La funzione upload
- Lavorare con i file
serie di lezioni per Web deve- teristiche. - Funzioni base e variabili - La gestione degli errori
loper. Capiremo cosa siano un Da- - I costrutti di controllo - Accenni di sicurezza
Nella prima parte conclude- tabase System e un DBMS (Da- - DataBase: il database
remo il corso di PHP sviluppa- tabase Management System) e Lezione 2: system
to nelle due precedenti lezioni, vedremo i principi basilari per - Approfondiamo PHP - Siti Web dinamici
approfondendo gli ultimi aspet- la corretta costruzione di una - Include e require - Teoria dei database
ti pratici di programmazione e base di dati. - Funzioni e classi
introducendo alcuni suggeri- Al termine di questa lezione - Proteggere una pagina Le prossime puntate
menti generali in termini di ge- saremo quindi in grado di pa- - Cookie e sessioni
stione degli errori e di sicurez- droneggiare PHP e la teoria dei - La funzione mail Lezione 4: PHP e MySQL
za. DB, pronti a unire queste due Lezione 5: Gestire un sito
La seconda parte, invece, è conoscenze nelle due puntate Lezione 3: PHP e i database dinamico con PHP e MySQL
dedicata all'introduzione dei restanti del corso.

2 Upload di file
ella prima le- ne dello spazio a nostra dispo- sia perché, accidentalmente o Ci sono tre cose cui prestare

N zione abbia-
mo visto co-
me installare un
sizione.
Spesso solo webmaster,
webdesigner e webcontent,
volutamente, potrebbero can-
cellarne tutti i contenuti.
attenzione (listato 01): la parti-
colare istruzione enctype nel-
l'intestazione del form (senza
I listati server locale per ognuno per la sua area di com- Come effettuare l’upload la quale l'operazione non viene
completi poter testare off li- petenza, si occupano di carica- dei file svolta), l'imposizione della di-
sono sul CD ne in tutta calma le re contenuti nel sito, ma in al- La soluzione è quindi creare mensione massima (in byte)
pagine PHP prima cuni casi potremmo voler dare una pagina Web attraverso la del file caricabile e il type “file”
di caricarle sul no- la stessa possibilità anche ai quale compiere l'operazione di dell'istruzione di input.
stro spazio Web. nostri visitatori (o ai nostri upload dei file. A seconda dei
clienti). nostri scopi la pagina potrà es- Listato_01
L’accesso FTP del provider Pensiamo, ad esempio, al ca- sere o no protetta, consenten- <form enctype="multipart/form-data"
Per compiere questa opera- so di un sito di viaggi amato- do l'accesso ai soli utenti auto- action="file_upload.php"
zione il provider ci avrà asse- riali che voglia consentire agli rizzati. method="post">
gnato un accesso FTP (File utenti (meglio se registrati) di PHP è in grado di ricevere fi- <input type="hidden" name="MAX_
Transfer Protocol) protetto da caricare (uploadare) le imma- le (in forma testuale o binaria) FILE_SIZE" value="100000">
username e password, accesso gini della loro ultima vacanza, o direttamente da un form di una File da inviare: <input name="mio"
grazie al quale saremo in grado ad un sito di un ente pubblico pagina Web e ci fornisce una type="file" size="40"><p>
di spostare, aggiungere, can- in cui una persona designata si serie di funzioni di autentica- <input type="reset" value="Cancella"
cellare, rinominare file diretta- occupi di caricare le delibere di zione e manipolazione grazie >&nbsp;<input type="submit"
mente sul server remoto come interesse pubblico senza do- alle quali abbiamo un comple- value="Invia">
stessimo utilizzando il ben co- ver ogni volta passare attra- to controllo su quanto viene </form>
nosciuto Esplora Risorse di verso il webmaster. caricato e sulla sua gestione fu-
Windows. È chiaro che queste persone tura. Il file individuato dopo aver
Possiamo anche fare l'u- non devono assolutamente Costruiamo per prima cosa premuto il bottone sfoglia (o
pload di immagini, filmati, file avere accesso tramite FTP alla il form di inserimento, come vi- browse se abbiamo impostato
musicali; l'unico limite è gene- struttura del sito Web, sia per sibile nella pagina form_ la lingua inglese di visualizza-
ralmente dato dalla dimensio- motivi di sicurezza e privacy upload.php. zione) viene caricato in memo-

PC Open 106 Dicembre 2004


3a lezione

1 te vedere nella pagina // il nome del file è stato diviso


file_upload.php (listato 03) e le in più parti registrate nel vettore
informazioni restituite sono vi- $nomi. Il separatore è il punto.
sibili nell'immagine 1; la cartel- $estensione=$nomi[count($nomi)-1];
la di destinazione scelta è // estraggo l'ultimo valore del
“upload/” e il percorso è indi- vettore: questa è l'estensione
cato in modo relativo. Termi- del file originale
nata l'operazione il file tempo- $ammesse=array("jpg", "gif", "txt");
raneo sarà cancellato dalla me- // questo è il vettore con le
moria. estensioni da me consentite
Attenzione: move_uplo if (in_array($estensione,$ammesse)) {
ded_file sovrascrive file esi- // con in_array controllo se
stenti senza chiedere alcun l'estensione del file rientra tra
permesso. quelle ammesse
[...]
listato_03
$dir="upload/".$_FILES['mio']['name']; Ricordiamo che va assoluta-
if (move_uploaded_file($_FILES mente impedito il caricamento
['mio']['tmp_name'], $dir)) { di file con estensioni PHP dal
echo "Il file è stato caricato con momento che tali file potreb-
successo. Ecco le informazioni di bero eseguire operazioni di-
Informazioni di debug utili per l’upload di un file debug:\n<pre>"; struttive all'interno del nostro
print_r($_FILES); spazio Web: non va mai dimen-
} ticato, infatti, come PHP sia an-
ria come file temporaneo e // esempio: “costruzione.gif” che un potentissimo linguaggio
quindi indirizzato alla pagina fi- echo "Tipo di file: Non è difficile impostare dei di scripting.
le_upload.php. La dimensione ".$_FILES['mio']['type']."<br>"; controlli basati sulla dimensio- È possibile anche caricare
massima del file è in realtà de- // esempio: “image/gif” ne del file o sul tipo: come più file contemporaneamente
finita a livello server nel php.ini echo "Dimensione del file: esempio potete studiare la pa- utilizzando le caratteristiche
(valore della riga upload_max_ ".$_FILES['mio']['size']."<br>"; gina form_upload_txt.php (cari- dei vettori per inserire le istru-
filesize; di default è 2 MB) e fa // esempio: 4783 bytes ca i file passando attraverso fi- zioni input da utilizzare:
testo indipendentemente dal echo "Nome temporaneo file: ".$_ le_upload_txt.php) in cui è im-
valore scritto a livello di form. FILES['mio']['tmp_name']."<br>"; postato un controllo per con- <input name="mio[]" type="file">
Definire qui un valore può però // esempio: sentire solo il caricamento di fi-
rivelarsi utile per due motivi: “C:\winnt\temp\php22.tmp” le tipo testo. Con qualche controllo nella
per restringere le dimensioni echo "Tipo di errore: Non sempre, però, il valore pagina ricevente (se il codice
dei file che vogliamo far carica- ".$_FILES['mio']['error']."<br>"; restituito da $_FILES['file']['ty- errore è 0 allora il file in que-
re o per evitare che un utente // esempio: “0” pe'] è sufficiente per definire il stione può essere caricato, al-
attenda il caricamento di un fi- ?> tipo di file che si sta caricando, trimenti significa che c'è un er-
le per poi vedersi restituito un ed inoltre questo valore in al- rore o che la casella di carica-
errore (le dimensioni del file Il valore “0” di $_FILES cuni casi dipende, purtroppo, mento è stata lasciata vuota) i
sono confrontate con quanto ['mio']['error'] indica che il ca- dal browser usato dall'utente. nostri file verranno caricati nel-
indicato nel php.ini solo dopo il ricamento in memoria è avve- Per evitare problemi si può agi- la directory scelta.
caricamento in memoria!). nuto in maniera corretta (vedi i re in modo da ricavare l'esten- Gli esempi citati sono nelle
Dopo il caricamento PHP ci codici risultanti dall’interroga- sione del file (i tre ultimi carat- pagine form_upload_plus.php e
mette a disposizione il vettore zione più avanti nell’articolo). teri dopo il “.”), per poi con- file_upload_plus.php, disponi-
globale $_FILES, grazie al quale In questo momento il file è an- frontarla con un vettore di bili nel CD Guida.
otteniamo una serie di infor- cora nella memoria tempora- estensioni “ammesse”.
mazioni sul file: il nome origi- nea; per effettuare fisicamente L'esempio riportato in
nale, il “mime type” (se il brow- l'upload utilizziamo una funzio- form_upload_check.php e fi- I codici risultanti
ser è abilitato a fornire questa ne che si occupa di spostare un le_upload_check.php tiene con- dall'interrogazione
informazione), la dimensione file caricato in memoria nella to anche dei file con più esten- $_FILES['nome
in byte, il nome del file tempo- sua destinazione finale: sioni (tipo “pippo.txt. php”) input']['error']
raneo e il codice di errore. estraendone solo l'ultima significano:
Queste cinque chiamate so- move_uploaded_file (file_caricato, (quella effettivamente valida) e
no riportate nel listato 02, e so- destinazione); confrontandola con le esten- 0 => il file è stato caricato
no caratterizzate da cinque pa- sioni consentite (listato 04). correttamente in memoria
role chiave (name, type, size, Questa funzione restituisce L'esempio è utile anche per
tmp_name, error) poste dopo true solo se l'operazione va a conoscere due nuove funzioni: 1 => la dimensione del file
il nome assegnato al file da ca- buon fine, quindi è necessario explode (trasforma in vettore eccede quanto stabilito nel php.ini
ricare nell'operazione di input che il file sia correttamente ca- una lista una volta definito un
(nel nostro caso era <input na- ricato e (fondamentale) che la separatore dei termini) e in_ar- 2 => la dimensione del file
me="mio" type="file" si- destinazione sia una cartella ray (controlla se un valore è eccede quanto indicato nel form
ze="40">): cui siamo abilitati in scrittura presente in un vettore).
(in caso di dubbio chiedere al 3 => il file è stato caricato
listato_02 provider se e quali sono le car- listato_04 parzialmente
<?php telle cui si è abilitati in scrittu- <?php
ra volendo caricare un file da selezionato nessun file nel form
echo "Nome del file: form Web). $nomi=explode('.', di upload
".$_FILES['mio']['name']."<br>"; L'esempio completo lo pote- $_FILES['mio']['name']);

PC Open 107 Dicembre 2004


3a lezione

3 Lavorare con i file


bbiamo già parzialmente zione del link e le informazioni

A
listato 05
visto come lavorare coi fi- <select name="nome" size="1"><option></option> sul giorno e l'ora del clic: que-
le e con le directory quan- <?php sto file potrà poi essere editato
do abbiamo introdotto le fun- $cartella=@opendir('upload'); con un foglio elettronico per ri-
zioni basename, opendir e while (false !== ($file = readdir($cartella))) { cavarne delle statistiche.
readdir nelle lezioni preceden- $lista[]=$file; Il sorgente della pagina
ti, e lo stesso caricamento di fi- } link.php ci mostra come otte-
le appena visto è un altro esem- $lista=array_slice($lista,2); nere questo risultato. Per pri-
pio di utilizzo delle funzioni fi- // array_slice lo uso per eliminare le indicazioni . e .. presenti in readdir. ma cosa impostiamo la sezione
lesystems di PHP. Abbiamo a È un sistema più veloce per compiere la stessa operazione vista HTML: non ci sono difficoltà,
disposizione numerosissime nella prima lezione salvo l'accortezza di indicare
funzioni pronte all'uso (sem- foreach ($lista as $nomi) { ogni link in questo modo:
pre che si abbia la pazienza di echo "<option>".$nomi."</option>";
leggere il manuale), sta solo a } <a href="link.php?url=http://
noi trovare la maniera migliore ?> www.pcopen.it">PC Open</a><p>
di operare. </select> // link.php è la pagina dove ci
Nel paragrafo precedente, troviamo. L'url del link viene qui
ad esempio, move_uploaded_ assegnato alla variabile
file ha rivelato il difetto di so- form. Potremmo migliorare l'e- lettura e/o scrittura, posizionando il $_GET['url']
vrascrivere, senza avvertire, i sempio (pagina puntatore all'inizio o alla fine del file.
file presenti nella cartella. Me- checkcan_plus.php) creando un Usando un sistema windows è La sezione PHP (in testa al
glio predisporre, quindi, un form (vedi listato 05) con una meglio usare sempre l'opzione codice sorgente della pagina
controllo in grado di verificare casella a discesa nella quale aggiuntiva “t” come “mode” per i file link.php) contiene il codice che
la presenza o meno di un certo siano presenti tutti i file della testo e “b” per i file binari. consente di scrivere nel file (li-
file nella directory esaminata. cartella “upload”: selezionan- fread ($handle, length); stato_06). Per prima cosa viene
La funzione è: done uno possiamo decidere di // legge il contenuto di un file controllato che esista
cancellarlo o di vederne alcune aperto dal descrittore $handle. Se $_GET['url'], il che vuol dire
file_exists ($nome); caratteristiche con la funzione length non è settato, il file viene che qualcuno ha cliccato su
// $nome comprende il percorso pathinfo (immagine 2). letto fino alla fine. uno dei link. Poi viene assegna-
di ricerca del file e il suo nome Vedendo il listato originale, fwrite ($handle, $content); to un nome al file di testo dove
noterete che sono state usate // scrive $content sul file aperto dal verranno registrati i dati per le
Potremmo anche desiderare @opendir e @unlink: nel prossi- descrittore $handle statistiche: scegliamo di dargli
cancellare un file presente in mo paragrafo vedremo a cosa fclose ($handle); un nome del tipo “annosetti-
una cartella: in questo caso la serve la @ davanti al nome di // chiude il file aperto dal mana.txt”, in modo da avere fi-
funzione da utilizzare è: una funzione. descrittore $handle le separati per ogni settimana
PHP consente di lavorare (usiamo le funzioni di data già
unlink ($nome); non solo con i file, ma anche Con poche nozioni siamo in viste nella lezione 1). Il succes-
// $nome comprende il percorso “sui” file: possiamo, infatti, grado di creare un paio di sivo ciclo if si occupa di defini-
di ricerca del file e il suo nome aprire e modificare i file scri- esempi interessanti. Supponia- re il descrittore $file e di aprire
vendo informazioni al loro in- mo di avere nel nostro sito una (eventualmente creare) il file
Un esempio concreto è pre- terno. Per questi scopi si usano pagina di link (immagine 3) e di annosettimana.txt, posizionan-
sente nella pagina checkcanc. una serie di funzioni specifi- voler sapere quali sono effetti- do il puntatore di scrittura al
php, attraverso la quale si può che: vamente cliccati e quante vol- termine del testo già inserito.
controllare se un file è presente te. Per avere queste informa- Mi occupo poi di definire la riga
nella cartella “upload” (ed $handle=fopen ($nome, mode); zioni può essere sufficiente da scrivere, inserendo il per-
eventualmente cancellarlo) // il descrittore $handle apre, scrivere su un file di testo delle corso del link, una tabulazione
semplicemente compilando il tramite la funzione fopen, un file in righe che contengano l'indica- (“\t”), la data e l'ora del click e,

2 3

Form per ricavare informazioni su un file e per cancellarlo Con PHP possiamo individuare i link più cliccati di una pagina

PC Open 108 Dicembre 2004


3a lezione

listato 06 listato 07
<?php $conteggio= fread($file,filesize($visite));
if (isset($_GET['url'])) { // assegno a $conteggio il valore che leggo nel file di testo
$nome_file = date("YW").".txt"; (dove c'è solo un numero)
// il file che verrà creato è del tipo annosettimana.txt, fclose($file);
if ($file=fopen($nome_file, 'at')) { $conteggio++;
// apro il file o lo creo. $file è il "descrittore"; il mode "a" serve // incremento il contatore
a posizionare il puntatore alla fine del file, il mode "t" serve per la $file = fopen($visite,"w");
modalità testo per Windows fputs ($file,$conteggio);
$ins = $_GET['url']."\t"; // scrivo il nuovo valore sul file eliminando il precedente
$ins.= date('d/m/Y H:i')."\n";
fwrite($file, $ins);
// scrivo la stringa $ins passando alla funzione fwrite 4
il descrittore
fclose($file);
// chiudo il file passando alla funzione fclose il descrittore
}
header("Location: ".$_GET['url']);
// indirizzo l'utente al link su cui aveva cliccato
}
?>
Il file testo ottenuto indica quali link risultano più visitati

per ultimo, l'indicazione di fine http://127.0.0.1/lezione_3/link.php? gnando il valore ad una varia- mo visto che possono rivelarsi
riga (“\n”). url=http://www.linux.org bile. Quindi, chiuso il file (è estremamente utili anche se,
Ora non ci resta che scrivere // scrive nel file di testo un link non buona norma tenere i file aper- per le loro caratteristiche, non
la riga con fwrite, chiudere il fi- compreso nella pagina originale ti il meno possibile), incremen- possono sostituire i database.
le con fclose e indirizzare il no- tiamo il valore trovato e riscri- Come al solito, per approfondi-
stro utente (in maniera del tut- Bisognerebbe dunque pre- viamo il file con questo nuovo re e conoscere tutte le funzioni
to trasparente per lui) verso il vedere dei controlli di inte- valore. Queste nuove operazio- filesystems di PHP bisogna leg-
link cliccato. grità, e senza dubbio un lavoro ni sono riportate nel listato 07. gere l'ottimo manuale di
Il file di testo ottenuto sarà migliore lo si otterrebbe regi- Ogni volta che la pagina conta- PHP.net; questo anche per evi-
del tipo visibile in immagine 4. strando i dati in un database. tore.php verrà caricata vedre- tare, magari chiedendo aiuto in
Adesso siamo in grado, con po- Ma questo lo impareremo nelle mo aumentare di una unità il un newsgroup, di sentirsi ri-
che modifiche al file originale, prossime lezioni; l'importante valore visualizzato. spondere con l'acronimo
di aggiungere a piacere tutta in questo frangente era solo di- Lavorare coi file può non es- RTFM, ossia “Read the f... ma-
una serie di informazioni come mostrare come non sia troppo sere sempre facile, ma abbia- nual!”.
il browser del visitatore e il suo difficile lavorare sui file con
indirizzo remoto. E adesso non PHP. 5
ci resta che analizzare il nostro Il secondo esempio (pagina
file settimanale delle statisti- “contatore.php”) consente di
che dei link. creare un rudimentale contato-
Certo questo è un buon si- re per le nostre pagine (imma-
stema, ma non è ottimale e in- gine 5), mantenendo memoriz-
fatti si presta a piccole “mano- zato il valore nel file di testo
missioni” esterne: ad esempio “conteggio.txt”.
si può aggiungere una riga al fi- Rispetto all'esempio prece-
le di testo anche senza cliccare dente, in questo caso dobbia-
su nessun link, semplicemente mo prima leggere il contenuto
scrivendo un URL del tipo del file conteggio.txt, asse- Un semplice contatore delle visite della pagina

4 La gestione degli errori


crivendo del codice è In tutti questi casi PHP ci tre un fatal error ne causa l'im- definendo la funzione somma.

S sempre possibile fare


qualche errore. Si può in-
trodurre nella sintassi qualche
viene in aiuto con una serie di
messaggi di errore che spesso
ci consentono di capire al volo
mediata interruzione e quindi
impedisce la lettura del codice
successivo (la pagina errori.
Questo debug è stato utile per
noi programmatori, ma potreb-
be essere fonte di problemi se
costrutto errato o si possono cosa c'è di sbagliato nel codice. php dovrebbe mostrare una ri- venisse visto dai visitatori di
eseguire operazioni proibite o L'esempio errori.php genera i ga di testo alla fine). questa pagina, oltre alla brutta
bloccate dalle regole che le de- messaggi visibili in immagine 6: Leggendo con attenzione il figura che faremmo: l'utente,
finiscono. Esempi possono es- Abbiamo ottenuto come ri- reporting di PHP, possiamo infatti, vedrebbe informazioni
sere: cercare di dividere un nu- sultato tre avvertimenti (war- trarre i necessari suggerimenti sui listati e sulle pagine, non-
mero per zero, oppure chiama- ning) e un errore grave (fatal per correggere il nostro codice, ché nome e indirizzo di un file
re una funzione con un nome error). La differenza risiede nel eliminando quindi il divisore da includere (con qualche in-
inesistente o includere un file fatto che un warning non bloc- zero, creando il file pippo.txt tuizione, potrebbe tentare di
esterno non presente. ca la lettura della pagina, men- nella cartella upload e infine accedere direttamente ai file 

PC Open 109 Dicembre 2004


3a lezione

 della cartella upload). Peggio zazione di tutti i messaggi di er- 6


ancora, potremmo dare indica- rore che potessero manifestar-
zioni sull'indirizzo e sul nome si in una pagina inserendo, al-
utente del server su cui risiede l'inizio del codice:
il nostro database (lo vedremo
nelle prossime lezioni). <?php
Bisogna quindi porre atten- error_reporting (E_NONE);
zione alla gestione degli errori: // oppure error_reporting(0);
la prima cosa da conoscere è il // controllate sul manuale le opzioni
settaggio del php.ini, settaggio di error_reporting per poter
visibile, al solito, tramite la pa- scegliere di visualizzare solo certi
gina phpinfo.php (vedi prima errori, tipo E_ERROR,
lezione). Probabilmente trove- E_WARNING,...
remo: ?>

error_reporting = 2039 Provate, come verifica, a ca-


(ossia tutti i messaggi di errore ricare la pagina errori_no.php,
sono visualizzati tranne alcuni dopo aver controllato che il co-
warning che non sono considerati dice sorgente sia lo stesso del-
comunque errati) la pagina errori.php: non verrà
In questa schermata sono raccolti alcuni errori in PHP
display_errors = On visualizzato nulla.
log_errors = Off Questo, però, è un rimedio
drastico, mentre PHP ci con-
Questo settaggio indica che sente di usare anche delle so- non davanti a cicli condiziona- $file = '/upload/pippo.txt';
tutti gli errori verranno visua- luzioni puntuali. Una sfrutta l'o- li come if o foreach. Su un $apri = @fopen($file, 'r') or
lizzati e non saranno registrati peratore di controllo errori “at” esempio del paragrafo prece- die("<h3>Non è stato possibile aprire
in un file di log. Se siamo uten- (@): la famosa chiocciolina @ dente si era usata @ davanti al- il file $file</h3>");
ti remoti c'è solo da tenere in davanti ad una espressione l'istruzione unlink per impedire
considerazione questo fatto, PHP impedisce l'eventuale vi- che venisse visualizzato un In questo esempio, la @ im-
mentre se siamo “padroni” del sualizzazione di un messaggio warning se si tentava di can- pedisce la visualizzazione del
nostro server andrebbe presa di errore (pagina errori_at. cellare un file non presente nel- messaggio di warning, poi il co-
in considerazione l'ipotesi di php): la cartella: per lo scopo dell'e- dice, fallita la chiamata a fopen,
inibire la visualizzazione dei sempio, infatti, il non trovare il è bloccato da die.
messaggi di errore consenten- $b=0; file non era da considerarsi un Alcuni errori, invece, li pos-
done, al contempo, la registra- $c = @ ($a/$b); errore e quindi non doveva siamo evitare sfruttando ade-
zione in un file di log. Dal mo- // non viene visualizzato il warning comparire alcun messaggio. guatamente il codice. È perciò
mento, però, che la situazione che ci aspetteremmo per avere Nel caso di uno script (ad buona abitudine utilizzare dei
standard è la prima (sul server diviso un numero per zero esempio l’apertura di un file o cicli if insieme alle funzioni fi-
remoto non abbiamo alcun po- connessione a un database), le_exists, function_exists e
tere), vediamo cosa possiamo @ funziona solo quando si accanto ad @ si può usare il co- method_exists, per accertarsi
fare per gestire al meglio gli er- trova davanti ad un'espressio- strutto die (alias di exit) per che file, funzioni e metodi delle
rori. ne che deve restituire un risul- bloccare il codice nel punto in classi cui facciamo riferimento
Un intervento drastico è tato, quindi va bene per chia- cui lo script fallisce (pagina er- esistano realmente nel proget-
quello di impedire la visualiz- mate di funzioni e include, ma rori_die.php): to che stiamo sviluppando.

5 I consigli per rendere il sito (più) sicuro


icurezza è un concetto agli amministratori di sistemi. tette impostando i permessi, di sempre i tag standard <?php

S ampio che coinvolge mol-


teplici aspetti: i dati sul si-
stema e i dati in transito, i pro-
Nel nostro piccolo, invece,
possiamo dedicare qualche
sforzo all'evitare errori banali
ed evitiamo anche di lasciare
nella root pagine come la ph-
pinfo.php che può dare infor-
e ?>.
Seconda accortezza: quan-
do viene incluso un file (con in-
tocolli, il server hardware, il di programmazione, cercando mazioni importanti ad un po- clude o require) in una pagina
Web server software, le appli- di fare quindi la nostra parte tenziale attaccante. Web, teniamo presente che
cazioni Web e le persone. Tutti nella catena della sicurezza. La prima accortezza, poi, questo file esiste fisicamente
questi aspetti sono correlati, e Sono piccoli accorgimenti ine- consiste nel non usare mai, an- nel nostro spazio ed è accessi-
basta una falla in un qualsiasi renti quanto abbiamo visto in che se il settaggio di php.ini lo bile direttamente col browser
punto per rendere “insicuro” queste puntate e di cui magari consentisse, gli short tag <? e se si conosce l'indirizzo remo-
tutto il sistema. abbiamo già parlato, ma è bene ?> o gli asp tag <% e %> per in- to. Dal momento che gli include
Non è questa la sede per ad- richiamarli per concludere dicare al browser l'inizio del sono spesso usati per registra-
dentrarci in disquisizioni sulle adeguatamente il discorso su codice PHP. Un cambio di set- re dati importanti, funzioni e
politiche di sicurezza da adot- PHP. taggio, infatti, renderebbe il co- classi, bisogna impedirne la vi-
tare, né avrebbe senso parlare Come base di tutto, faccia- dice visibile a tutti (magari in- sualizzazione diretta. Ricordia-
della sicurezza server-side di mo attenzione a cosa inseria- sieme a password e parametri moci, quindi, di salvare il file
Apache e PHP, argomenti sui mo nella Web root: teniamo i di connessione), oltre a impe- con estensione finale .php,
quali spesso non abbiamo con- dati sensibili in cartelle diver- dire la corretta visualizzazione usando poi i tag php nel modo
trollo diretto e che lasciamo se, magari adeguatamente pro- delle pagine Web. Usiamo quin- appropriato.

PC Open 110 Dicembre 2004


3a lezione

Anche i messaggi di errore utente inserisse il carattere jol- 7


possono causare falle nella si- ly del linguaggio di interroga-
curezza, quindi, oltre a con- zione “%”? Senza un controllo
trollare attentamente il codice di validazione, il risultato finale
scritto, si può disabilitare la vi- sarebbe la cancellazione di tut-
sualizzazione dei messaggi nel- ti i record.
le pagine caricate sullo spazio Le sessioni hanno un nome
Web. identificativo predefinito: PH-
L'operazione di upload di fi- PSESSID. A questo nome si fa
Un problema di vulnerabilità facilmente evitabile
le può essere pericolosissima spesso riferimento per propa-
se si lascia l'utente libero di ca- gare l'id di sessione o per regi-
ricare qualsiasi tipo di file, ma- strarlo su un cookie. Sarebbe ray superglobali $_POST[], trollo semplicemente scriven-
gari contenenti script PHP in meglio, però, che il nome della $_GET[], $_SESSION[] e do sul browser l'URL in questo
grado potenzialmente di can- sessione lo assegnassimo noi: $_COOKIE[]. In questo modo si modo: vulnerabile.php?autenti-
cellare tutto il nostro lavoro. cosa succederebbe, infatti, se può distinguere, ad esempio, cato=1 (immagine 7). Se invece
Essenziale, quindi, è porre un un domani venisse cambiato $_GET['nome'] da $_SES- il controllo fosse stato su
controllo sul tipo di file che è nel php.ini questo valore pre- SION['nome'], dove il primo va- $_COOKIE['autenticato'] non
possibile uploadare e sulle car- definito? Il nostro codice non lore deriva dall'URL della pagi- avremmo potuto fare nulla (ve-
telle dove permettiamo il cari- funzionerebbe più come ave- na mentre il secondo deriva da dere vulnerabile_no.php). Chia-
camento. vamo previsto. una sessione inizializzata, e al ramente se register_globals fos-
Attenzione va posta ai form: L'ultima raccomandazione fa contempo non è definita nes- se stato Off anche il primo me-
in alcune circostanze abbiamo riferimento al settaggio regi- suna variabile globale $nome. todo non avrebbe più funzio-
bisogno di passare alcuni valo- ster_globals di php.ini. Fino alla Anche se il vostro provider nato.
ri “nascosti” e li inseriamo col versione 4.2 il valore di default avesse mantenuto il valore di Con questi consigli il mini-
type=”hidden” in un'istruzione era On e questo consentiva di register_globals a On, è impor- corso di PHP come strumento
input. Ricordiamoci che questi registrare le variabili col loro tante comunque usare sempre stand-alone si è concluso e
valori sono perfettamente visi- nome, indipendentemente dal- e solo gli array superglobali adesso tocca ad ognuno ap-
bili a tutti: basta semplicemen- l'input. In pratica, una variabile per non incappare nel proble- profondire la conoscenza di
te visualizzare il codice sor- $nome presente in una pagina ma visibile nella pagina vulne- questo potentissimo linguag-
gente HTML della pagina. Altro poteva derivare da un input di rabile.php: poniamo che in que- gio. Nelle prossime puntate ve-
aspetto importante è control- tipo get come da un input di ti- sta pagina venga fatto un con- dremo, invece, come interfac-
lare cosa viene inserito nei po post o da un cookie o da una trollo su una variabile $autenti- ciare PHP con un database in
campi del form, validando sem- sessione. cato definita da un cookie. Se modo da aumentare considere-
pre i dati. Immaginate, ad Questo causava problemi di carichiamo la pagina veniamo volmente le nostre azioni di
esempio, di avere creato un vulnerabilità, quindi il settag- bloccati (non abbiamo un webdeveloper. Ma per far que-
form per consentire la cancel- gio di register_globals è stato cookie nella nostra memoria sto dobbiamo capire bene cosa
lazione di record da un databa- posto a Off e per riferirsi alle dove sia definita la variabile), sono le basi di dati, come ve-
se. Cosa succederebbe se un variabili si devono usare gli ar- ma possiamo bypassare il con- diamo di seguito.

6 I database
e tecnologie basate sui da- è certamente un database, in nate azioni (inserimento, recu- Il database system
L tabase (letteralmente “rac-
colte di dati”) giocano un
ruolo critico in tutte le aree fon-
quanto è una collezione di dati
aventi un significato implicito
(nome, indirizzo, telefono) e tra
pero, aggiornamento, cancella-
zione dati). Un libro, quindi,
non è un database, mentre lo è
La rappresentazione grafica
un ambiente di sviluppo “mo-
derno” di un database è visibile
damentali della nostra vita: loro correlati. Anche la pagina un dizionario. in figura 8. A valle, memorizzato
pensiamo, ad esempio, all'uso di un libro, però, potrebbe es- Un database può contenere in un qualsivoglia mezzo elet-
di database per consentire la sere vista come un database in più o meno dati ed essere più o tronico, c'è il database fisica-
gestione del nostro conto in quanto rappresenta una colle- meno complesso: pensiamo, ad mente esistente, composto dai
banca, per prenotare delle visi- zione di parole tra loro collega- esempio, alla nostra agenda te- dati e dalle informazioni sulla
te in ospedale, per verificare gli te. Così non è, dal momento lefonica e alla banca dati di un sua stessa struttura (meta-da-
esami effettuati all'università, che un database è considerato gestore di telefonia. Una base di ti).
per la gestione delle aziende tale quando ha queste pro- dati potrebbe essere gestita an- Per creare il DB, accedervi e
(coi software ERP) e via dicen- prietà: che manualmente, ma all'au- interrogarlo utilizzeremo un
do. • rappresenta uno o più aspetti mentare della complessità DBMS (DataBase Management
Ne sentiamo tanto parlare, del mondo reale (il cosiddetto avremo bisogno di un supporto Systems), ossia un'applicazio-
ma cos'è realmente un databa- “minimondo”); tecnologico e informatico per ne in grado di processare delle
se? Volendo semplificare al • è una collezione di dati logi- costruire ed utilizzare il DB, e richieste e di accedere ai dati in
massimo la definizione, possia- camente coerenti tra loro e coe- nel contesto di questo corso gli scrittura e lettura. MySQL è un
mo vederlo come una collezio- renti con la descrizione della strumenti scelti sono il databa- DBMS, come lo sono anche Mi-
ne di dati tra loro correlati, do- realtà scelta (non è, quindi, un se MySQL e PHP. Dal punto di crosoft Access e SQL Server,
ve per “dati” intendiamo dei va- insieme di dati messi a caso); vista informatico un database è PostgreSQL, Oracle e moltissi-
lori conosciuti che possono es- • è disegnato, costruito e po- assimilabile ad una tabella tipo mi altri programmi.
sere registrati e hanno un signi- polato per un certo gruppo di foglio elettronico, con i distin- Per utilizzare il DBMS, infine,
ficato implicito. Da questo pun- utenti interessati ad interagire guo che vedremo in un para- servirà un'applicazione in gra-
to di vista un'agenda personale con esso compiendo determi- grafo successivo. do di inviare una richiesta: po- 

PC Open 111 Dicembre 2004


3a lezione

 trebbe essere un'interfaccia 8


dello stesso DBMS, ma può es-
sere anche un software o un lin- Programmatori e utenti
guaggio esterno come PHP o
ASP. Tutte le parti qui descritte
vanno a formare il database sy-
stem, ossia l'insieme di softwa- Database
re, interfacce, applicazioni che Programmi applicativi e query
servono all'utente per interagi- system
re totalmente con una base di
dati.
Il DBMS è il componente fon-
damentale del sistema perché Software per elaborazione programmi e query
consente di gestire i processi di
definizione, costruzione e ma-
nipolazione della base di dati. DBMS
Definire un database signifi-
(Database
Management Software per l’accesso ai dati
ca specificare il tipo, la struttu- System)
ra e i vincoli dei dati che saran-
no memorizzati, mentre co-
struire il DB implica il processo
di registrazione dei dati sul
“mezzo” controllato dal DBMS.
Struttura Dati
Manipolare la base di dati si-
(meta-dati)
gnifica, infine, creare le interro-
gazioni in grado di recuperare,
aggiornare e cancellare i dati
(riflettendo le variazioni del L’”ambiente” globale di sviluppo di un database
“minimondo” rappresentato
dal database), nonché di gene- se, però, torniamo al nostro developer? Quali vantaggi ci sarà necessaria per eseguire il
rare dei report (a video o a corso. Ci serve un database? porta? Capito questo dovremo lavoro nella maniera più effi-
stampa). Cosa ci consente di fare rispet- affrontare la costruzione ex no- ciente) e imparare ad interro-
Fatte queste debite premes- to alle nostre esigenze di Web vo di un DB (un po' di teoria garlo.

7 Siti Web dinamici


lla base della creazione di cune riguardano solo il com- delle pagine da effettuare quan- tabase contenente gli oggetti

A un sito Web sta la fonda-


mentale attività della pro-
gettazione, il momento in cui le
mittente, ma quasi certamente
la risposta a queste domande
riguarderà poi noi.
do il nostro cliente volesse
esporre nuovi prodotti.
Se non abbiamo esplicitato
dell'artigiano da cui estrarre i
dati da visualizzare sulla pagi-
na Web.
richieste e le idee del commit- Ricordiamoci, e lo insegna bene il significato di questo ag- In questo modo ogni modifi-
tente devono essere esplicita- ogni settore dell'economia, che giornamento, potremmo tro- ca/aggiunta/cancellazione ai
te, e spesso “tradotte” in un lin- è meglio “spendere” tempo in varci due problemi, opposti ma prodotti andrebbe fatta diret-
guaggio concreto, in una serie fase di progettazione (quando i ugualmente potenzialmente tamente sul database (un'ope-
di punti programmatici. costi della modifica sono bas- gravi: dover fare troppi aggior- razione, come vedremo pre-
Chi ci affida il lavoro, infatti, si) piuttosto di accorgersi in fa- namenti, o doverne fare uno sentando il linguaggio SQL,
ha ben chiaro (o dovrebbe se avanzata che si potevano solo dopo molti mesi. Nel pri- molto facile e per la quale po-
averlo) il contenuto del mes- percorrere strade alternative: a mo caso il problema per noi è tremmo preparare un'interfac-
saggio da comunicare, il modo questo punto fare delle modifi- dover continuamente prendere cia grafica, ad esempio con
di comunicarlo e il target cui ri- che diventerebbe molto costo- in mano il codice HTML, modi- PHP) ed automaticamente la
volgersi, ma probabilmente so perché tante decisioni di ficare le pagine e ricaricarle pagina Web sarebbe aggiorna-
non ha mai pensato ai retro- struttura sarebbero ormai ulti- nello spazio Web; nel secondo ta. Certo questo sistema di la-
scena di questi aspetti per il mate. Il costo della modifica è caso dovremmo riguardare del voro ci “costerebbe” di più in
presente e il futuro. chiaramente massimo quando codice scritto mesi prima, rie- fase realizzativa, ma ne benefi-
Chi crea i testi? Con quale il progetto è realizzato. Il com- saminando il progetto (che ma- ceremmo in seguito. Anzi, po-
cadenza potrei doverli cambia- mittente potremmo anche es- gari ha condotto un nostro col- tremmo addirittura proporre al
re? Se cambio un testo, quale sere noi stessi e la validità di laboratore che non lavora più cliente, in cambio di un prezzo
sarà la procedura per il nuovo quanto scritto sopra restereb- per noi) e facendo infine l'ago- maggiore di realizzazione del
inserimento? È possibile/pro- be immutata. gnato aggiornamento. In en- sito, di fare lui stesso queste
babile avere esigenze di am- Prendiamo come esempio trambi i casi il rischio che il co- operazioni di modifica dando-
pliamento dei menu del sito? un caso concreto: supponiamo sto del tempo utilizzato non gli così anche una libertà gene-
Se ci sono delle news chi le in- di aver realizzato un sito aven- sia stato coperto dal prezzo ralmente molto apprezzata.
serisce? Ogni modifica cosa te lo scopo di essere la “vetri- pattuito col cliente è alto. Potremmo stabilire delle
comporta? Chi fa la gestione? na” dei prodotti di un artigiano Quale sarebbe potuta essere aree nelle quali riservare al
Queste sono solo alcune do- e di aver pattuito un compenso una soluzione migliore? Utiliz- cliente l'aggiornamento (noti-
mande che ci si deve porre. Al- per un anno di aggiornamento zare un DBMS per creare un da- zie, domande e risposte, comu- 

PC Open 113 Dicembre 2004


3a lezione

 nicati e via dicendo) e mante- ti con la relativa votazione. È 9


nere per noi, invece, l'aggior- chiaro come non sia neppure
namento delle altre. Insomma, concepibile pensare di creare
un sistema di gestione a data- tante pagine “statiche” (tutte
base può consentirci, pur pa- protette da password) quanti
gando il prezzo di una proget- sono gli studenti immatricolati,
tazione più onerosa, di separa- vuoi per esigenze di spazio
re fisicamente il concepimento (forse il problema minore) vuoi
della pagina (template) dal suo per tutte le implicazioni di ag-
riempimento, rendendo que- giornamento che la scelta com-
st'ultima un'operazione più porterebbe. In questo caso,
semplice e veloce in caso di ag- quindi, l'unica soluzione è crea-
giornamenti. re il template della pagina “esa-
Ci sono poi i casi in cui uti- mi”; la pagina verrà poi dina-
lizzare dei database è assoluta- micamente riempita con i dati
mente necessario perché la dello studente che effettua la
La richiesta di una pagina gestita da un database da parte degli utenti A e B
mole di dati e l'utilizzo che se richiesta di visualizzazione del (tra parentesi l'ordine delle operazioni)
ne fa renderebbe impossibile la suo piano studi. I dati saranno
gestione di pagine “statiche”. ospitati in un database costan-
Un esempio, che poi useremo temente aggiornato in maniera vantaggio: eventuali modifiche La stessa strutturazione la
per costruire da zero un DB, veloce ed economica. La strut- di layout della pagina sono ese- troviamo nei siti di home
possono essere le pagine di un tura dell'interrogazione e della guite, una sola volta, esclusiva- banking, in quelli di commercio
ateneo che voglia mettere i risposta è visibile schematica- mente sul template e immedia- elettronico, nei siti Web edito-
propri studenti in grado di ac- mente in figura 9. Questa ge- tamente sono attive per ogni ri- riale e l'elenco potrebbe conti-
cedere alla lista degli esami fat- stione porta anche un altro chiesta di pagina. nuare a lungo.

8 Teoria dei database


vendo deciso di sfruttare i agli studenti, dati relativi ai cor-

A
10
vantaggi offerti dalle basi si ed agli esami e dati relativi ai
di dati per il nostro sito, ci professori.
troviamo adesso nella neces- Il primo passo è realizzare lo
sità di creare un DB efficiente. schema concettuale: è uno
Fondamentale, ai nostri fini, è schema non utilizzabile diretta-
che il database non abbia infor- mente dal DBMS, ma fornisce
mazioni ridondanti (ossia non concetti vicini a quelli utilizzati
abbia duplicazioni di dati) per- da una persona nel percepire e
ché questo comporterebbe concettualizzare la realtà og-
spreco di memoria, minore effi- getto di studio (il minimondo). Lo schema concettuale: modello Entità-Relazione
cienza del sistema e la probabi- Useremo, data la sua diffusione
le introduzione di inconsisten- e la sua intuitività, il modello
ze e/o perdite di dati. Entità-Relazione proposto da dati registrati nell'entità (l'i- di E2 corrispondono (possono
Per ottenere questo risultato P. Chen nel 1976 (la figura 10 stanza). Ciò significa che non ci corrispondere) più istanze del-
si compiono delle operazioni riassume come rappresentare potranno essere due istanze l'altra entità coinvolta.
di modellizzazione allo scopo graficamente lo schema con- con lo stesso valore: questo at- Un esempio, con la rappre-
di esplicitare la struttura finale cettuale). Questo modello uti- tributo è detto chiave. Anche sentazione dei tipi di relazione
del DB che andrà creata col lizza come base il costrutto En- una relazione può contenere e degli attributi, è visibile inve-
DBMS scelto. Questo primo tità: rappresenta un oggetto degli attributi. ce in figura 11. Le entità coin-
passo, da fare anche con carta della realtà che, ai fini dell'ap- Ultimo sforzo è definire il vin- volte sono quattro (studente,
e penna, è forse il più noioso, plicazione di interesse, ha una colo di relazione tra due entità, piano studi, corso, professore)
ma è assolutamente importan- propria identità (è “distinguibi- vincolo classificabile con una di ed esemplificano i tre vincoli di
te e vale quanto detto in prece- le” dagli altri oggetti) ed ha una queste tipologie: relazioni previste:
denza: meglio dedicare molto esistenza fisica (es: studente, • 1:1 (uno-a-uno; one-to-one): • studente - inserisce - piano
tempo alle fasi progettuali piut- professore) o concettuale (es: ad ogni istanza di E1 corrispon- studi = relazione 1:1 -> ogni stu-
tosto di accorgersi alla fine del- corso, piano di studi). Ogni en- de (può corrispondere) una ed dente deve inserire un solo pia-
la necessità di modificare la tità è messa in relazione con al- una sola istanza di E2 e vice- no di studi, e ogni piano di stu-
struttura per renderla più effi- tre entità, da cui il nome dello versa; di deve essere riferito ad un so-
ciente. schema, allo scopo di definirne • 1:N (uno-a-molti: one-to- lo studente. In questo esempio
Come esempio di lavoro vo- le reciproche corrispondenze. many): ad ogni istanza di E1 abbiamo assunto che non vi
gliamo creare lo schema di un L'entità è accompagnata da una corrispondono (possono corri- siano piani di studi standard tra
database il cui scopo è memo- serie di attributi che ne descri- spondere) più istanze di E2, i quali uno studente possa sce-
rizzare i dati degli studenti uni- vono le proprietà elementari mentre ad ogni istanza di E2 gliere (la relazione sarebbe sta-
versitari: in particolare ci inte- (es: matricola, nome, data, vo- corrisponde (può corrisponde- ta 1:N)
ressa conoscere la situazione to), ed uno di questi attributi (o re) una sola istanza di E1; • studente - fa la tesi con - pro-
degli esami svolti, quindi do- la combinazione di due o più) • N:N (molti-a-molti; many-to- fessore: relazione 1:N -> ogni
vremo registrare dati relativi deve definire univocamente i many): ad ogni istanza di E1 o studente può (se ha concluso 

PC Open 114 Dicembre 2004


3a lezione

gli esami) fare la tesi con un so- • per ogni relazione N:N si crea- 11
lo professore (il relatore ufficia- no tre tabelle corrispondenti
le), mentre ogni professore può alle due entità coinvolte ed alla
avere N tesisti. relazione che intercorre tra lo-
• studente - fa esami del - corso: ro. Quest'ultima tabella avrà co-
relazione N:N -> ogni studente me chiave primaria la combi-
può dare gli esami di N corsi, ed nazione delle chiavi delle altre
ogni corso può essere oggetto due tabelle.
di esami da parte di N studenti. Lo schema che ne esce è vi-
Terminato lo schema concet- sibile in figura 13. L'ultimo sfor-
tuale, per creare fisicamente il zo prima di avere uno schema
DB dobbiamo passare allo sche- efficiente si chiama normaliz-
ma logico il quale sarà imple- zazione: è un procedimento, in
mentabile direttamente nel più fasi, che interviene sulla
DBMS. Vi sono vari tipi di sche- struttura delle tabelle di un da-
ma, ma il miglior compromesso tabase e sui collegamenti tra es- Schema concettuale: un esempio di
tra qualità e semplicità è dato se. La trattazione approfondita modello Entità-Relazione
dal modello relazionale propo- del tema esula dal presente cor-
sto da E. Codd (primi anni '70). so, ma vale la pena accennare a
Il modello si basa, semplice- tre consigli previsti dalle Forme 12
mente, su un unico costrutto Normali.
detto relazione. Questa relazio- Il primo prevede di usare in
ne è una tabella (useremo da tutte le tabelle attributi univoci
adesso questo termine per non (non ripetuti) e semplici (non
ingenerare confusione con lo composti). Questo vuol dire
schema concettuale) con le se- che un'ipotetica tabella “stu-
guenti caratteristiche (figura denti” non deve mai compren-
12): dere una serie di colonne del ti-
• un numero prestabilito di co- po Esame1, Esame2... EsameN
lonne (detti anche campi o at- (l'attributo è sempre Esame, e
tributi) di cui va stabilito il tipo non va mai ripetuto), né deve
di valori (testo, numerico, ecc) comprendere un campo Esame Esempio di una relazione (tabella) nel modello Relazionale
e il loro eventuale dominio; se all'interno di questo voglio
• un numero variabile di righe registrare più di un dato (es: co-
(dette anche record o tuple o dice esame, votazione, data, rire, come anagrafica, nella ta- to scritto, il nostro DB è già
istanze); professore). In entrambi i casi bella Studenti: questi campi di- molto affidabile ed efficiente,
• uno o più campi formeranno va prevista la creazione di una pendono solo dal Comune di re- ed è pronto per essere inserito
la chiave primaria della tabella, tabella da legare a quella stu- sidenza indicato, non dalla ma- nel DBMS.
il cui valore identificherà uni- denti: in effetti è quello che ab- tricola dello studente che è la Nella prossima puntata ve-
vocamente un record. biamo fatto nel nostro esempio. chiave della tabella. Anche in dremo come creare il DB con
In linea di massima si potrebbe Il secondo consiglio è di questo caso va prevista una ta- MySQL e come compiere le
anche pensare di costruire un creare una nuova tabella cui fa- bella esterna che leghi un Co- operazioni di inserimento, ag-
DB con una sola grandissima re riferimento se siamo costret- mune al suo CAP ed alla Pro- giornamento e cancellazione
tabella, ma questo manifeste- ti ad inserire continuamente va- vincia di appartenenza. imparando ad usare il linguag-
rebbe immediatamente proble- lori ripetuti. Un esempio banale Un altro accorgimento, di gio universale di interrogazione
mi di ridondanze e anomalie. Il potrebbe essere il dipartimento buon senso, è di non memoriz- delle base di dati: SQL, ovvero
modello di Codd, per evitare di appartenenza di un profes- zare mai dati che possano es- lo Structured Query Language.
questo, si basa sulla teoria ma- sore: a forza di inserire il nome sere calcolati, quindi mai regi- Infine vedremo come usare
tematica dei sistemi e per ga- del dipartimento rischiamo di strare un campo “Età” se si ha a PHP per interfacciarsi con My-
rantire l'integrità e le coerenza commettere errori di digitazio- disposizione l'anno di nascita. SQL e portare su Web i risultati
dei dati vi sono delle regole ne pregiudicando ricerche fu- Se abbiamo rispettato quan- delle operazioni compiute. 
aventi lo scopo di creare N ta- ture, e inoltre se un diparti-
belle, più piccole possibili, da mento cambiasse nome do- 13
mettere in collegamento tra lo- vremmo modificare uno a uno STUDENTE PIANO STUDI
ro attraverso i valori delle chia- tutti i valori già inseriti. 1
Matricola Codice
vi. Per passare dallo schema Meglio, quindi, creare una ta-
Nome
1 Presentato il
concettuale a quello logico si bella “Dipartimenti” cui fare ri-
usa un algoritmo di “traduzio- ferimento: in questo modo non Cognome
ne” (mapping): ci sarebbero errori di inseri- Città
• per ogni relazione 1:1 si crea- mento, l'aggiornamento verreb- 1
Codice piano
no due tabelle corrispondenti be fatto in un unico punto ed N
alle entità coinvolte. Tra i cam- automaticamente propagato a In tesi con ESAME
N
pi di una delle due tabelle si ac- tutti i record interessati della Matricola
clude, come chiave esterna, la tabella Professori. Codice corso
N
PROF CORSO
chiave dell'altra tabella; Ultimo consiglio è di non in-
• Per ogni relazione 1:N si crea- serire in una tabella dei campi C.F. Data Codice corso
1 Voto 1
no due tabelle corrispondenti che non siamo direttamente di- Nome Anno
alle entità coinvolte. Tra i cam- pendenti dai campi chiave del- Cognome Aula
pi della tabella del ramo N si ac- la tabella stessa. Un esempio Schema logico: esempio di modello
Città relazionale con indicazione degli Orario
clude, come chiave esterna, la possono essere i campi CAP e attributi di ogni tabella
chiave della tabella del ramo 1; Provincia che potremmo inse-

PC Open 115 Dicembre 2004


4a lezione

 A scuola con PC Open

Web Developer PHP di Federico Pozzato

1 MySQL e PHP
a terza lezione del corso ci è Per queste operazioni usere-
IL CALENDARIO DELLE LEZIONI
L servita per imparare i con-
cetti fondamentali relativi
alla costruzione di un database
mo MySQL, le istruzioni SQL
(Structured Query Language) e
il linguaggio PHP che ci forni-
Lezione 1:
- PHP con un server off line
- Il database system
- Siti Web dinamici
efficace ed efficiente. Prenden- sce adeguati strumenti di in- - Funzioni base e variabili - Teoria dei database
do spunto da un caso reale terrogazione e gestione remota - I costrutti di controllo
(creare una base di dati per me- del DB.  Lezione 4:
morizzare la carriera universi- Se qualcuno ha avuto diffi- Lezione 2: - PHP e MySQL
taria di uno studente), abbiamo coltà ad installare o configura- - Approfondiamo PHP - MySQL, database
visto come costruire uno sche- re i programmi citati nelle scor- - Include e require opensource
ma concettuale ed il conse- se puntate e quelli introdotti in - Funzioni e classi - Costruzione e interrogazione
guente schema logico, tenendo questa lezione (come Apache, - Proteggere una pagina di un database: il linguaggio
conto delle tecniche di norma- PHP, MySQL e PhpMyAdmin), - Cookie e sessioni SQL
lizzazione per garantire l'inte- provi a fare riferimento al sito - La funzione mail - Interfaccia GUI: PhpMyAdmin
grità del database e la rilevanza easyPHP (http://www.ea- - Integrazione MySQL e PHP
dei dati. Quanto descritto ha syphp.org). Questo sito, di ori- Lezione 3: PHP e i database
validità assolutamente genera- gini francese e tradotto anche - La funzione upload La prossima puntata
le: adesso, però, è il momento in lingua italiana, è chiaro e ag- - Lavorare con i file
di implementare i nostri schemi giornato e fornisce in un unico - La gestione degli errori Lezione 5: Gestire un sito
su un DBMS e rendere interatti- pacchetto autoinstallante i pro- - Accenni di sicurezza dinamico con PHP e MySQL
va la nostra base di dati. grammi citati.

2 MySQL, un database opensource I listati


completi
o schema logico di una ba- MySQL nasce grazie alla sve- ma anche come DBMS per so- mera installazione

L se di dati va implementato
utilizzando un DBMS (Data-
base Management System), il
dese TcX (ora MySQL AB), una
società cui serviva un DB velo-
ce, flessibile e affidabile. Non
luzioni interne ad un'attività,
ad esempio per gestire la con-
tabilità, le spedizioni, le buste
di MySQL. Scari-
sono sul CD
chiamo da http://dev.mysql.
com/downloads/ l'ultima ver-
componente software che con- trovandolo tra i prodotti esi- paga o semplicemente per or- sione stabile di MySQL databa-
sente di operare i processi di stenti, i progettisti svedesi de- dinare una volta per tutte la se server and standard clients
definizione, costruzione e ma- cisero di crearselo distribuen- propria infinita collezione di li- per Windows (disponibile an-
nipolazione del database. dolo poi con licenza GPL (vedi bri. Il simbolo di MySQL è il del- che nel CD Guida 1 nella cartel-
Per il corso, coerentemente riquadro “Licenza GPL e licen- fino Sakila, per cui tuffiamoci la PDF\Corsi\PHP) e procedia-
con la scelta opensource effet- za commerciale di MySQL”). Il nel processo di installazione mo come al solito. Il processo è
tuata nelle lezioni precedenti, è risultato è un sistema in grado del software e nella creazione totalmente automatico se si ac-
stato scelto MySQL, un RDBMS di gestire con efficienza e sicu- del nostro primo database. cetta di installare il programma
libero (free) distribuito con li- rezza enormi moli di dati, con sulla cartella predefinita c:/my-
cenza GPL, basato sullo stan- una velocità di esecuzione di Installazione e avvio sql: approfittiamo di questa op-
dard SQL e disponibile per am- tutto rispetto. Ci sono ancora del server portunità lasciando l'alternati-
bienti Linux, Macintosh e Win- dei passi da fare per rendere MySQL è un cosiddetto da- va a chi voglia perdere qualche
dows. L'acronimo non è sba- MySQL veramente completo tabase server, e quindi per po- minuto in più per il settaggio
gliato: la R indica la parola “Re- (vedi “il futuro di MySQL” più ter funzionare necessita non successivo del file my.ini.
lational” a sottolineare come avanti nell’articolo), ma co- solo del software installato ma Terminata l'installazione fac-
MySQL (così come Postgre- munque le caratteristiche di anche di un server attivo (Apa- ciamo doppio clic sul file c:/my-
SQL, MS Access, Oracle e altri) questo database ne fanno un che, IIS, Xitami e via dicendo). sql/bin/winmysqladmin.exe per
sia un DBMS basato sul con- punto di riferimento assoluto Il nostro server è già impostato avviare per la prima volta il no-
cetto basilare di relazione tra del settore. Non solo sul Web, (vedi prima lezione), quindi stro server MySQL. Ci verrà
tabelle. dove è uno dei principali attori, concentriamoci sulla parte di chiesta una coppia user-pas-
4a lezione

sword: possiamo anche la- appena effettuata ci mette a di- del sistema, la persona cui è
sciarla in bianco dal momento
che questi parametri servono
sposizione un client con una
spartana interfaccia a caratte-
concesso il controllo assoluto
di MySQL, è l'utente root. Win-
Licenza GPL
solo in caso di amministrazio- ri, addirittura lanciata attra- dows crea automaticamente e licenza
ne remota del server MySQL. A verso una finestra DOS. quattro profili identificati da
questo punto avremo accesso La cosa non è così strana co- user, password e server di pro- commerciale
al pannello di gestione, rappre-
sentato da una icona a forma di
me potrebbe sembrare a prima
vista: MySQL, infatti, è un'ap-
venienza (localhost e remoto).
I profili, tutti generati senza
di MySQL
semaforo posta nella traybar plicazione server e l'interfaccia password predefinite, sono: La licenza GPL (GNU General
(immagine 1). Se il semaforo è client a caratteri consente di la- Public License) è la base del
verde, siamo pronti a creare il vorare con qualsiasi computer - root connesso da localhost: tutti sistema GNU/Linux e del
nostro primo database. indipendentemente dalle inter- i privilegi; software libero. Compilata da
facce grafiche installate e per- - root connesso da remoto: tutti Richard Stallman, questa licenza
1 mette di inviare facilmente co- i privilegi; impone, tra le altre cose, di
mandi via telnet da un compu- - utente anonimo connesso da ridistribuire liberamente il codice
ter collegato in rete. Inoltre ga- localhost: tutti i privilegi previsti per i sorgente di un programma che
Il semaforo verde conferma l'attivazione rantisce velocità e flessibilità, database presenti nel server; sia basato tutto, o in parte, su
del server MySQL chiedendo solamente di cono- - utente anonimo connesso da remoto: del codice soggetto a licenza
scere pochi comandi e le basi privilegi da assegnare. GPL. È il cosiddetto “effetto
Cliccando col tasto destro del linguaggio SQL. virale” (ossia contagioso) della
del mouse sul semaforo e sce- Naturalmente ci sono molte Questa configurazione è ac- licenza GPL. Dal 2001 MySQL
gliendo show me si apre la fine- interfacce grafiche già pronte cettabile finché usiamo il DB in AB, società che detiene i diritti
stra di gestione: potremo vede- (una la vedremo tra poco) per locale e lo curiamo solo noi, ma di MySQL ha deciso di fornire il
re sulla linguetta Environment semplificarci la vita, però al- è chiaramente pericolosa nel DB con una duplice licenza: GPL
(immagine 2) l'indirizzo IP lo- meno una volta è opportuno momento in cui al DB avessero e commerciale.
cale del nostro server (lo stes- utilizzare lo strumento di de- accesso altre persone o quan- La versione commerciale (a
so di Apache o IIS) e sulla lin- fault fornitoci, per capire le rea- do fosse messo in rete. La rac- pagamento) serve appunto a
guetta my.ini Setup i valori del li potenzialità di MySQL senza comandazione, quindi, è di superare il vincolo di libera
file my.ini: la riga che più ci in- farci distrarre da nessun aspet- cancellare subito l'utente ano- redistribuzione del codice:
teressa è la datadir che ci forni- to grafico. nimo connesso da localhost, chiunque, pertanto, desideri
sce il percorso di registrazione Sulla barra di Windows clic- assegnare le password a root e usare MySQL per applicazioni di
dei dati (utile saperlo per un chiamo su Start, Esegui e scri- creare degli utenti reali cui as- cui non vuole rendere pubblico il
backup). Sempre grazie al no- viamo cmd per aprire una con- segnare i privilegi voluti. codice sorgente dovrà
stro semaforo potremo ferma- sole DOS. Al prompt scrivia- Il manuale che si trova nella acquistare una licenza
re e far ripartire il servizio che mo: cd mysql\bin per portarci directory di installazione commerciale da MySQL AB.
presiede al funzionamento del sulla cartella di sistema di My- (C:\mysql\Docs\manual.html)
server MySQL. In alternativa SQL. è molto completo (salvato co-
per compiere la stessa opera- MySQL è studiato per appli- me file PDF occupa quasi 1.300 vizio. Ad esempio per fermare
zione possiamo usare l'utility cazioni client-server, quindi, pagine di formato A4) e si ri- il server si può scrivere:
Servizi che abbiamo a disposi- per motivi di sicurezza, utilizza manda alle pagine specifiche mysqladmin -u root -p shutdown
zione in Pannello di controllo, la gestione dei profili di acces- per queste operazioni. Per le (viene chiesta la password di root per
Strumenti di amministrazione. so degli utenti: a seconda delle esigenze didattiche di questo rendere effettiva l'istruzione)
autorizzazioni concesse (i co- corso vediamo però come in-
Client e sicurezza siddetti “privilegi”) gli utenti serire la password “pluto” per Useremo invece l'istruzione
Il server MySQL è stato av- potranno, ad esempio, solo fa- l'utente root (connesso da lo- mysql per aprire il client e agi-
viato, ma da solo non basta: re la gestione dei dati di data- calhost, ossia dal nostro server re sul database prescelto se-
per la gestione e per tutte le base specifici oppure creare interno) scrivendo questa riga condo quanto previsto dai no-
operazioni inerenti i database nuovi database ma senza poter (dalla console DOS): stri privilegi di accesso. Per
abbiamo infatti bisogno di uti- accedere ad altri oppure solo mysqladmin -u root -p password pluto collegarci scriviamo:
lizzare un client. L'installazione inserire dati. L'amministratore (verrà chiesto di inserire la password mysql -u root -p
vecchia: era vuota quindi basta solo
2 premere invio) e inseriamo la password. Se ci
troviamo di fronte un prompt
Fermiamo e facciamo ripar- (immagine 3) del tipo:
tire il server MySQL per carica- mysql>
re i nuovi privilegi. Da adesso
ci collegheremo al server e al Siamo pronti a gestire un da-
client MySQL con l'identità di tabase. Il client accetta due tipi
root e la password inserita. di inserimenti: comandi MySQL
o istruzioni SQL (da conclude-
Le prime istruzioni re sempre con un segno di pun-
Utilizzeremo l'istruzione my- to e virgola “;”). I comandi My-
sqladmin per compiere opera- SQL sono relativamente pochi
zioni “una tantum” che interes- (scrivere help per vederli) e ci
sano il server nella sua genera- interessano in particolar modo
lità: interrogazioni sullo stato, USE (per agire su un database
cambiare password, ma anche specificato) e QUIT (per uscire
creare e distruggere database dal client). Alle istruzioni SQL è
(cosa possibile anche utiliz- invece dedicato il prossimo pa-
I pannelli di configurazione del tool WinMySQLadmin zando il client) o fermare il ser- ragrafo. Come esempio scrivia- 
4a lezione

3 4

il client mysql è pronto ad accettare istruzioni e comandi

 mo queste righe attraverso le prompt “->”) e potremmo con-


quali accediamo al database tinuare a scrivere l'istruzione
“mysql” (è un DB installato in come fossimo sulla riga prece-
automatico e serve per la ge- dente. La chiusura dell'istru-
stione del DBMS. Non va can- zione necessita il “;” oppure il
cellato per nessun motivo) per costrutto “\g”.
poi vedere le tabelle che lo
compongono e infine uscire dal Il futuro di MySQL
client: Pur essendo un eccellente
prodotto per caratteristiche di
mysql > USE mysql velocità e di gestione dei dati,
(accediamo al DB mysql. Attenzione è MySQL non è ancora completo
un DB di sistema) sotto tutti i punti di vista.
mysql > SHOW tables; L'integrità referenziale, ad
(vediamo i nomi delle tabelle che esempio, è implementata solo
compongono il DB) per le tabelle di tipo InnoDB
mysql > DESCRIBE db; ma non per le MyISAM. Ricor-
Le risposte del server alle nostre prime interrogazioni: show e describe
(vediamo al struttura della tabella db: diamo che l'integrità referen-
immagine 4) ziale serve ad impedire che il
mysql > QUIT valore di un campo di una ta- mantenendo l'integrità referen- prossime release MySQL AB ha
(usciamo dal client) bella possa fare riferimento ad ziale, creare dei controlli al mo- già dato dei punti fermi: con la
un valore di campo chiave non mento di implementare l'inter- versione 4.1 troveranno sup-
La prima e la quarta riga non ancora esistente in una secon- faccia PHP. porto le sottoquery (serviran-
necessitano del “;” perché so- da tabella. Questa è una funzio- Altro limite è il mancato sup- no a semplificare le chiamate
no comandi MySQL, mentre la nalità importantissima per ga- porto delle views: le “viste” so- nidificate di tabelle che hanno
seconda e la terza sono istru- rantire la coerenza dei dati e no delle tabelle virtuali genera- lo scopo di creare un filtro di
zioni SQL. Se dimenticassimo il non essendo ancora supporta- te da query e saranno utilissi- ricerca), con la 5.0 le views e
“;” otterremmo solo l'effetto di ta dalle MyISAM dovremo, se me per semplificare il codice e con la 5.1 l'integrità referenzia-
andare a capo (col nuovo vogliamo usare queste tabelle ottimizzare le ricerche. Per le le per le tabelle MyISAM.

3 Costruzione e interrogazione di un database:


il linguaggio SQL
er costruire un database e di una ipotetica università (ve- (SQL:1999) e SQL:2003. Indi- filmati, immagini, file audio. È

P farlo funzionare adeguata-


mente abbiamo bisogno in
primis di conoscere il tipo di
di lezione n.3 su PC Open di di-
cembre 2004, disponibile an-
che in formato PDF nel CD Gui-
pendentemente dalla release,
la cosa fondamentale è avere a
disposizione per tutti i databa-
chiaro che l'efficienza del data-
base sarà direttamente pro-
porzionale alla corretta scelta
dati che dovranno essere me- da 3). se un linguaggio standard del tipo di dato di ogni campo
morizzati, passo necessario Per compiere queste opera- avente due specifiche caratte- (colonna): minore sarà lo spre-
per imparare a costruire una zioni, la creazione e la gestione ristiche: co di spazio, più veloci saranno
tabella. Dovremo poi assegna- del database, è indispensabile • è un linguaggio di definizione tutte le operazioni compiute
re il campo chiave, eventuali conoscere il linguaggio SQL dei dati (DDL, ossia DataDefini- sul DB. Fondamentale, quindi,
indici, valori predefiniti, il ran- (Structured Query Language). tion Language) è conoscere i tipi di campo che
ge di inserimento e così via. SQL, il cui nome originario • è un linguaggio di manipola- abbiamo a disposizione e sce-
Successivamente dovremo ap- era SEQUEL, fu inizialmente im- zione dei dati (DML, ossia Data gliere quello più adatto (attri-
prendere come gestire la no- plementato nei laboratori IBM Manipulation Language) buti compresi) alle nostre esi-
stra base dati tramite le azioni e venne poi standardizzato gra- Nei prossimi paragrafi ve- genze. Rimandando al manuale
di inserimento, modifica, can- zie allo sforzo congiunto di AN- dremo nello specifico come di MySQL per i dettagli, mentre
cellazione e interrogazione. SI (American National Standard usare SQL nel nostro RDBMS. nel box “I formati dei dati” rias-
Un esempio è necessario, Institute) e ISO (International sumiamo brevemente i tipi di
quindi partiremo dallo schema Standard Organization) che Tipi di dati dato.
logico sviluppato nella scorsa portò alla prima release stan- MySQL è in grado di gestire
lezione. Lo scopo è creare un dard denominata SQL1 (ANSI qualsiasi tipo di dato, e il ter- La costruzione di una tabella
database in grado di monitora- 1986). A questa sono seguite mine “qualsiasi” comprende MySQL consente di creare
re la situazione degli studenti SQL2 (SQL-92), SQL3 anche dati multimediali come diversi “tipi” di tabelle alle qua-
4a lezione

li corrispondono performance -> cognome VARCHAR(30) NOT NULL,


di risposta diverse. Le due più -> data_nascita DATE,
diffuse sono le MyISAM e le In- -> tesi_con CHAR(13), I formati dei dati
noDB. Le prime usano poca -> PRIMARY KEY(matricola), Il primo formato da esaminare è quello numerico, suddivisibile in numeri
memoria e sono gestite in ma- -> INDEX(cognome, nome); interi e decimali. Per i numeri interi (positivi e negativi) i campi disponibili
niera velocissima, però non -> ); (in ordine crescente di occupazione di byte) sono: TINYINT (1 byte),
hanno ancora tutte le funzio- mysql> EXPLAIN studenti; SMALLINT (2 byte), MEDIUMINT (3 byte), INT (4 byte) e BIGINT (5 byte).
nalità che si potrebbero desi- (per vedere la struttura della tabella Questo significa che un dato SMALLINT avrà un range totale di 2(2x8) =
derare, mentre le InnoDB, pur appena costruita) 65.536 valori divisi tra negativi e positivi (da – 32.768 a +32767, 0
essendo più complete, sono compreso). Se gli attribuissimo l'opzione UNSIGNED i valori sarebbero
più lente e chiedono un mag- Abbiamo creato una tabella solo positivi, quindi da 0 a 65.535. Un altro importante attributo dei
gior carico di memoria. definendo tutti i campi (due campi numerici interi è AUTO_INCREMENT: ogni nuovo record
Inizialmente useremo le ta- hanno un numero di caratteri incrementerà di una unità il valore del record precedente, e quindi diventa
belle MyISAM, visto che sono fissi, due hanno un numero di un campo chiave. Per i numeri decimali abbiamo a disposizione FLOAT,
quelle accettate di default. caratteri variabili, uno è una DOUBLE e DECIMAL (M,D). L'ultimo è particolarmente utile perché
Apriamo un client MySQL col- data di nascita), indicando il consente di definire il numero di cifre decimali (D) e il numero massimo
legandoci come root (in modo campo chiave (la matricola) e (M) di caratteri del numero, comprensivo di segno positivo o negativo e
da avere tutti i permessi possi- come indicizzare la tabella (pri- della virgola.
bili): al prompt la prima opera- ma per cognome e poi per no- Secondo formato è quello testuale (stringa). Se la stringa contiene meno
zione da fare è creare il databa- me). Gli indici sono fondamen- di 255 caratteri possiamo usare CHAR (M) o VARCHAR (M), con M numero
se UNIVERSITAS: tali per abbreviare le fasi di ri- massimo di caratteri. La differenza è che un campo CHAR occupa sempre
cerca, ma attenzione che indi- M byte indipendentemente dalla stringa inserita nel record, mentre
NB: in MAIUSCOLO sono indicate le care troppi indici porterebbe VARCHAR occupa un numero di byte uguale al numero di caratteri (più uno)
istruzioni specifiche di SQL ad un peggioramento delle pre- della stringa. Se il testo è maggiore di 255 caratteri useremo TINYTEXT,
mysql> CREATE DATABASE universitas; stazioni. TEXT, MEDIUMTEXT e LONGTEXT. Quest'ultimo consente di memorizzare
La tabella ESAMI sarà invece una stringa di testo di 4 GB! L'attributo BYNARY trasforma il testo in
Se volessimo cancellarlo l'i- così costruita: stringa binaria: la conseguenza è che MySQL distinguerà, nell'ordinamento
struzione sarebbe: mysql> CREATE TABLE esame ( delle ricerche, i caratteri minuscoli dai maiuscoli.
mysql >DROP DATABASE universitas; -> matricola VARCHAR(8) NOT NULL, Altro tipo di dato sono le stringhe di testo predefinite, rappresentate da
-> cod_corso SMALLINT UNSIGNED ENUM e SET. In questo caso il valore del campo (unico nel caso di ENUM,
Dobbiamo creare quattro ta- NOT NULL, anche multiplo nel caso di SET) può essere scelto solo tra valori predefiniti
belle: una con i dati degli stu- -> voto TINYINT NOT NULL, da noi in fase di creazione del campo.
denti, una con i dati dei profes- -> lode ENUM(no,si) DEFAULT no NOT Il formato multimediale è registrato come stringa di caratteri binaria nelle
sori, una con i dati dei corsi e NULL, forme di TINYBLOB, BLOB (Binary Large Object), MEDIUMBLOB e
una con i risultati degli esami. -> data DATE NOT NULL, LONGBLOB (4 GB di spazio!).
Ogni tabella andrà inizializzata -> PRIMARY KEY (matricola, Date e ore possono essere salvate in forma completa o parziale. Nel
indicandone prima il nome e cod_corso), primo caso abbiamo a disposizione TIMESTAMP (4 byte occupati, ma date
quindi tutti i campi che la com- -> ); limitate dal 1970 al 2037 su macchine a 32 bit) e DATETIME (8 byte
pongono, tipi di dato e attribu- occupati, dall'anno 1000 al 9999). Il formato di TIMESTAMP predefinito
ti compresi. La tabella STU- Qui si è introdotto un valore occupa 14 caratteri ed è memorizzato come AAAAMMGGHHMMSS;
DENTE sarà quindi implemen- booleano grazie al tipo di dato esistono comunque altri formati minori che possono essere maggiormente
tata in questo modo (le istru- ENUM (i valori possono essere adatti alle esigenze di costruzione del DB. Il formato di DATETIME è
zioni di creazione della tabella solo “no” o “si”. Il primo è il va- variabile e dipende dai dati effettivamente inseriti. Date e ore “parziali”
sono su più righe solo per ren- lore di default). Volendo essere sono gestibili, pur nei limiti loro assegnati di default, con DATE (dal 01-01-
dere più comprensibile il lista- precisi, anche il campo voto 1000 al 31-12-9999), TIME (consente valori negativi e supera
to): avrebbe potuto essere un abbondantemente le 24 ore: il formato è usabile, quindi, anche per calcoli
ENUM con valori compresi tra sugli angoli) e YEAR (dall'anno 1901 al 2155).
mysql> USE universitas; 18 e 30, ma visti i tempi di cam- Un piccolo spazio merita l'attributo NULL che può essere assegnato ad
(entriamo nel database appena creato: biamento lasciare libero il cam- ogni tipo di dato. Cos'è un valore null? Null vuol dire proprio “nessun
all'apertura del client è sempre po è forse meglio. valore” e non è né una stringa vuota (per un testo) né il valore zero (per i
necessario indicare quale DB useremo Capito il sistema, lasciamo ai numeri). Se sappiamo che un campo non potrà mai essere null è bene
come riferimento per le istruzioni lettori il compito di costruire le omettere questo attributo: in caso contrario verrebbe sempre salvato un
successive) altre tabelle: l'unica accortezza è bit extra per ogni campo che potrebbe essere null.
porre il campo codice nella ta-
mysql> CREATE TABLE studente ( bella CORSO (immagine 5) come
-> matricola CHAR(8) NOT NULL, TINYINT con l'opzione ve). Chi non volesse scrivere base creato off line sul PC di ca-
-> nome VARCHAR(30) NOT NULL, AUTO_INCREMENT (è una chia- tutto il codice può approfittare sa: tutti i provider fornitori di
del file universitas_db.sql: i file questo servizio consentono, in-
5 .sql sono dei file testo che con- fatti, sia l'importazione che l'e-
sentono di effettuare, tra le al- sportazione di file .sql.
tre cose, la procedura di I comandi da eseguire, dal
backup. Grazie a questi file sia- prompt del DOS una volta usci-
mo in grado di esportare (e im- ti dal client, sono:
portare) la struttura del data- mysqldump -u root -ppluto universitas
base (o della singola tabella) > universitas_db.sql
ed eventualmente anche i dati (backup di tutte le tabelle del database
inseriti. Questa opportunità si “universitas”, al momento senza dati.
rivelerà utilissima non solo per Il file creato si chiamerà
salvare i dati, ma anche per “universitas_db.sql”)
esportare su un server in Inter-
L'istruzione explain ci mostra la composizione della tabella CORSO net il nostro fiammante data- Attenzione: a causa di un 
4a lezione

 bug di alcune versioni (la 4.0.13 INSERT INTO tabella VALUES mento alla tabella “prof” non cando una condizione da ri-
ad esempio) la password di (campo_1, campo_2, ...); esistente. La stessa cosa acca- spettare per cancellare la riga o
root (la nostra “pluto”) in que- de se, al momento di registrare le righe in questione:
sta istruzione va inserita im- La differenza tra le due istru- il voto di un esame, inseriamo DELETE FROM tabella [WHERE
mediatamente dopo l'opzione zioni è che la prima consente di una matricola errata o un codi- condizione];
“-p” senza spazi intermedi. In indicare (nell'ordine che prefe- ce di un corso inesistente. Que- (la clausola where è opzionale: se c'è
generale è sempre comunque riamo) solo i campi che voglia- sto, è dovuto al mancato sup- vengono cancellati solo i record che
possibile inserire la password mo effettivamente riempire porto dell'integrità referenziale rispettano la condizione, altrimenti
in questo modo in ogni istru- con dei valori (gli altri saranno delle tabelle MyISAM. vengono cancellati tutti i record della
zione di comando dalla shell completati in accordo con le Se volessimo avere questo tabella)
del DOS. Se la versione che ave- caratteristiche definite per i supporto avremmo dovuto de-
te installato è esente dal bug, campi della tabella), mentre la finire tutte tabelle (ogni tabella Ad esempio se volessi can-
fate a meno di inserire la pas- seconda istruzione ci impone ci sono riferimenti a valori di cellare tutti gli studenti di co-
sword sulla riga di comando, di scrivere tutti i valori dei chiave esterni) utilizzando il gnome “Rossi”, l'istruzione
scrivendola invece solo quan- campi di un record (comprese “type” InnoDB e i comandi FO- sarà:
do richiesto come visto in pre- quindi stringhe vuote, valori REIGN KEY - REFERENCES di mysql> DELETE FROM studente
cedenza. Altri comandi che po- null o predefiniti) esattamente SQL: WHERE cognome=”Rossi”;
tremmo scrivere sono: nell'ordine in cui è costruita la mysql> CREATE TABLE studente
tabella. L'utilizzo dell'una o del- (matricola CHAR(8) NOT NULL, nome La modifica dei dati può es-
mysqldump -u root -ppluto -d l'altra istruzione dipende dal VARCHAR(30) NOT NULL, cognome sere fatta su tutti i record di
universitas studente corso > tipo di inserimento che dob- VARCHAR(30) NOT NULL, data_nascita una tabella o su delle tuple se-
universitas_parz.sql biamo fare. DATE, tesi_con CHAR(13), PRIMARY lezionate con un'apposita con-
(backup dei soli dati delle tabelle Poniamo di voler inserire un KEY(matricola), INDEX (tesi_con, dizione:
'studente' e 'corso' del database valore nella tabella studenti: cognome, nome), FOREIGN KEY UPDATE tabella SET campo_1=
“universitas”: il file creato è mysql> INSERT INTO studente SET (tesi_con) REFERENCES prof(cod_fisc)) aggiornamento_1, campo_2=
“universitas_parz.sql”. L'opzione -t cognome=”Rossi”, nome=”Antonio”, TYPE=INNODB; aggiornamento_2, ... [WHERE
avrebbe fatto il backup della sola matricola=”912345IG”, (il riferimento alla tabella prof è dato condizione];
struttura senza i dati. Va inserita la data_nascita=”19780427”; con l'istruzione FOREIGN KEY: bisogna (la clausola where è opzionale e serve
password di root) (ho inserito nella tabella studente, però ricordare di indicare il campo a restringere il numero di record da
nell'ordine che volevo, solo i dati cui “tesi_con” anche negli indici) aggiornare)
mysql -u root -p universitas < volevo attribuire un valore. Svantaggio
universitas_db.sql è che devo ricordare i nomi corretti dei Così facendo siamo obbliga- Un esempio potrebbe essere
(ripristino o inserimento, nel database campi) ti ad inserire nel campo “te- un cambio del professore con
già creato “universitas”, delle tabelle si_con” un valore già presente cui fare la tesi da parte di uno
oggetto di backup contenute nel file Equivalente sarebbe stata l'i- nella tabella “prof”. A titolo di studente ben preciso, identifi-
“universitas_db.sql”. Le tabelle non struzione: esempio, nel CD trovate il file cato con la sua matricola:
vengono sovrascritte) mysql> INSERT INTO studente VALUES universitas_innodb.sql che con- mysql> UPDATE studente SET
(“912345IG”, “Antonio”, “Rossi”, tiene la struttura del database tesi_con=”BBBCCC52B41A123B”
Eseguendo l'ultima istruzio- “19780427”, null); costruita con tabelle InnoDB e WHERE matricola=”123456IG”;
ne avrete il vostro database uni- (qui avrei dovuto inserire tutti i valori tutte le integrità referenziali ri-
versitas completo della struttu- nel giusto ordine, compreso l'ultimo spettate. Caricando queste ta- Altro esempio: supponiamo
ra di tutte le tabelle e pronto ad valore null perché questo studente belle si noterà l'impossibilità di di dover trasformare tutti i vo-
essere gestito. Se il file universi- ancora non è in tesi con alcun caricare dati non coerenti con ti (al momento espressi in tren-
tas_db.sql non fosse nella car- professore. Il vantaggio in questo caso quanto definito in termini di tesimi) in voti centesimali. Ba-
tella “bin” di mysql (quella dove è che non devo inserire i nomi dei integrità referenziale. Lo spazio sta una modifica su tutta la ta-
ci troviamo per eseguire il co- campi) occupato dalle tabelle, però, bella “esame” (immagine 7):
mando), andrà indicato il per- aumenta considerevolmente e mysql> UPDATE esame SET
corso assoluto completo (ad Chiaramente se tentassimo calano le performance di velo- voto=voto*10/3;
esempio: D:\backup\mio\uni- di inserire una matricola (cam- cità.
versitas_db.sql). po chiave) già esistente ci ver- Torniamo al DB con tabella Esiste poi anche il comando
Da questo momento in poi rebbe segnalato un errore (im- MyISAM: il file universitas_da- REPLACE che combina le ca-
daremo per scontato di essere magine 6). Notiamo che l'inse- ti.sql contiene dei valori di ratteristiche di INSERT e UP-
connessi al client MySQL e di rimento della data va fatto nel esempio da caricare per popo- DATE e quindi può fare al con-
trovarci nel database universi- formato corretto (AAAAMM lare il database. Carichiamo tempo funzioni di inserimento
tas (istruzione use universitas). GG) e che ad un eventuale pro- questo file come abbiamo già e aggiornamento.
fessore con cui si fa la tesi ci si imparato e proseguiamo la le-
La gestione dei dati deve riferire tramite il codice fi- zione. Interrogazione
Il database è adesso solo scale, ossia il campo chiave La cancellazione dei dati di dei dati (query)
uno scheletro vuoto, ma que- della tabella “prof”. una tabella può essere fatta in L'interrogazione (query, dal
sta era la parte più difficile. Ge- Non ci viene dato errore se maniera “completa” ossia can- verbo “to query” = interroga-
stire i dati è, al confronto, un'o- inseriamo nel campo cellando tutti i record oppure, re) del database è senza dub-
perazione piuttosto agevole e “tesi_con” un valore di riferi- ed è il caso più frequente, indi- bio l'operazione più utilizzata
vedremo come fare l'inseri- nella gestione di un database,
mento, la cancellazione la mo- 6 ed è al contempo facile e com-
difica dei medesimi usando plessa. La facilità deriva dalla
sempre le istruzioni SQL. strutturazione dell'interroga-
L'inserimento può essere fat- zione standardizzata da SQL,
to in più modi: mentre la sua complessità de-
riva dalla strutturazione rela-
INSERT INTO tabella SET campo_1= zionale della base di dati che ci
valore_1, campo_2=valore_2,...; MySQL ci indica un errore se tentiamo di inserire due studenti con la stessa matricola impone spesso di dover estrar-
4a lezione

7 MIN (trova il valore più basso) 8


e AVG (calcola la media). Se
non sono specificati raggrup-
pamenti queste funzioni agi-
ranno tenendo conto di tutti i
record estratti: ad esempio per
sapere quanti sono gli studenti
nati dal 1980 in poi:
mysql> SELECT COUNT(*) FROM
studente WHERE data_nascita >=
”19800101”; Una query esatta ma che non consente
una leggibilità immediata
Il raggruppamento si rivele-
Risultato di un update completo sulla tabella esame rebbe utilissimo se volessimo 9
sapere la media voti di ogni
re informazioni da più tabelle bella “corso” (immagine 9): studente (immagine 10). Uso
tra loro collegate. Quest'ultima mysql> SELECT corso.nome, anche la funzione alias AS che
operazione prende il nome di esame.voto, esame.lode serve ad assegnare un nome
JOIN. -> FROM corso, esame nuovo momentaneo (in genere
Una query nella sua struttu- -> WHERE corso.cod_corso=esame. per motivi di maggiore chiarez-
ra più completa è così scritta cod_corso za) ad un campo (esistente o
(le clausole tra parentesi qua- ->AND esame.matricola=”123456IG” creato con la query) o ad una
dre sono opzionali): -> ORDER BY data; tabella:
SELECT campi_tabella/e mysql> SELECT matricola, AVG(voto) La stessa query con un join diventa molto
FROM tabella/e Un join, quindi, si fa estraen- AS media più significativa e leggibile
[WHERE condizione]; do i dati utili da più tabelle (i -> FROM esame
[GROUP BY raggruppamento] nomi dei campi vanno indicati -> GROUP BY matricola; di operatori aritmetici, logici, di
[HAVING condizione_raggruppamento] anteponendo il nome della ta- confronto, di ricerca e binari.
[ORDER BY campi_tabella/e bella cui fanno riferimento) e Sulla clausola di raggruppa- Abbiamo a disposizione fun-
ASC/DESC] imponendo, nella clausola mento potremmo porre delle zioni numeriche (ABS, LOG,
WHERE, una condizione di ulteriori condizioni tramite COS, ...), funzioni di controllo
Alcuni esempi sono: uguaglianza tra determinati va- HAVING per rendere ancora più dei cicli (IF, IF NULL, CASE),
lori delle tabelle: in questo ca- interessanti le nostre interro- funzioni per agire sulle strin-
mysql> SELECT cognome, nome FROM so il join è fatto sul campo che gazioni. ghe (CONCAT, UPPER, ...), fun-
studente; identifica il codice numerico Ad esempio poniamo di vo- zioni di data e ora e funzioni
(selezioniamo solo le colonne del corso, campo chiave ester- ler conoscere il nome degli stu- per la sicurezza (PASSWORD,
cognome e nome, con quest'ordine, no per la tabella “esame” e denti che hanno fatto almeno ENCRYPT,...). Ad esempio per
dalla tabella studente) campo chiave effettivo per la tre esami: estrarre le date di nascita degli
tabella “corso”. Abbiamo intro- mysql> SELECT studente.nome, studenti rendendole “leggibili”,
mysql> SELECT * FROM studente; dotto anche la clausola ORDER studente.cognome FROM studente, potremmo usare (immagine
(con l'asterisco selezioniamo tutte le BY che serve a ordinare i risul- esame 11):
colonne dalla tabella studente) tati (di default in maniera -> WHERE studente.matricola= mysql> SELECT CONCAT(nome, “
ascendente, altrimenti si deve esame.matricola “,cognome) AS nome_studente,
mysql> SELECT * FROM studente aggiungere DESC) dell'interro- -> GROUP BY esame.matricola DATE_FORMAT(data_nascita,
WHERE cognome=”Rossi”; gazione. -> HAVING COUNT(*)>=”3”; “%d-%m-%Y”) AS data
(selezioniamo solo i record della Introduciamo la parola chia- (“having” agisce solo su una clausola -> FROM studente
tabella studente per i quali il valore di ve DISTINCT: serve ad elimina- “group by”) -> ORDER BY cognome, nome;
“cognome” è “Rossi”) re da un risultato eventuali tu-
ple duplicate che si otterreb- Queste sono le principali 10
Spesso, però, avremo biso- bero. Supponiamo di volere sa- istruzioni di una query. SQL
gno di operare un join, ossia la- pere il numero di matricola de- comprende poi una ulteriore
vorare con più tabelle correla- gli studenti che hanno supera- serie di utili operatori su insie-
te. Supponiamo di voler sapere to almeno un esame: queste mi (UNION, EXCEPT, INTESECT,
quali sono gli esami sostenuti matricole saranno presenti nel- CONTAINS), operatori “quanti-
dallo studente con matricola la tabella esame, ma una query ficatori” (ALL, ANY, IN, NOT IN,
123456IG. Una query come la semplice presenterebbe dupli- SOME) e operatori di verifica
seguente è formalmente esatta cati se uno studente avesse (EXISTS, NOT EXISTS, UNIQUE)
perché ci dà i codici dei corsi, passato più di un esame. Per che si lasciano al libero studio Come calcolare la media voti usando la
però non ci restituisce i nomi evitarlo e avere il risultato vo- degli interessati ad approfon- clausola di raggruppamento e la funzione
degli esami corrispondenti (im- luto si scriverà: dire l'argomento. AVG di SQL
magine 8): mysql> SELECT DISTINCT matricola
mysql> SELECT cod_corso, voto, lode FROM esame; Operazioni sulle query: 11
FROM esame WHERE comandi principali
matricola=”123456IG” ORDER BY Molto utili, infine, sono le Sui record estratti da una
data; funzioni aggregate che agisco- query si può agire in un secon-
no sulla totalità dei record do momento, ad esempio inter-
quindi per dare leggibilità al ri- estratti, secondo una precisa venendo coi costrutti di PHP,
sultato dobbiamo fare un join condizione di raggruppamen- oppure si può agire diretta-
(“to join” = unire) per sostituire to: COUNT (conta il numero di mente al momento dell'estra- Il risultato di una query può essere
al codice il corrispondente no- record), SUM (somma i valori), zione del risultato. SQL, infatti, sottoposto a varie operazioni prima di
me del corso ricavato dalla ta- MAX (trova il valore più alto), fornisce una libreria completa essere stampato
4a lezione

4 Un’interfaccia GUI: PhpMyAdmin


inora, per i motivi già scrit- fig.inc.php. Cerchiamo la riga magine 12) da cui possiamo mandi MySQL per analizzare e

F ti di universalità, abbiamo
usato l'interfaccia a caratte-
ri per agire su MySQL, però in
contenente $cfg['PmaAbsolu-
teUri'] e dopo il segno di ugua-
glianza indichiamo il percorso
partire per fare praticamente
tutto quello che vogliamo (se
ne abbiamo i permessi) su da-
ottimizzare le tabelle della ba-
se di dati.
PhpMyAdmin è un ottimo
certe occasioni un'interfaccia da raggiungere tramite server: tabase, tabelle e singoli dati. strumento e vale sicuramente
grafica può aiutarci a compiere $cfg['PmaAbsoluteUri'] = Possiamo inserire i privilegi de- la pena usarlo per applicazioni
certe operazioni di cui, magari, 'http://127.0.0.1/phpMyAdmin'; gli utenti, esportare e importa- interne, ma ricordate che il vo-
non ricordiamo perfettamente (o http://localhost/phpMyAdmin o ...) re database salvati in formato stro provider potrebbe fornirvi
la costruzione. .sql o .zip, scrivere query aiu- un'interfaccia grafica diversa, o
Introduciamo quindi una uti- Poi immediatamente dopo tati dalla grafica, inserire, mo- addirittura non fornirvela af-
le GUI (Graphic User Interface) cerchiamo dificare e cancellare dati, con- fatto.
rilasciata sotto licenza GPL e $cfg['Servers'][$i]['host'] trollare lo stato del server My- Per tutte le opzioni di confi-
totalmente scritta in PHP per SQL, vedere l'ingombro delle gurazione, veramente molte, si
interagire con MySQL: e scriviamo l'indirizzo IP del tabelle e la loro velocità di ri- rimanda al manuale fornito col
PhpMyAdmin. nostro server MySQL interno: sposta, e agire anche su dei co- programma.
L'installazione non compor- $cfg['Servers'][$i]['host'] = “localhost”
ta problemi: è sufficiente, infat- (o 127.0.0.1 o ...) 12
ti, scompattare il file zippato
(lo trovate nel CD oppure su e poi di fianco a
http://www.phpmyadmin.net/h $cfg['Servers'][$i]['auth_type']
ome_page/) in una cartella che
chiameremo “phpMyAdmi” da scriviamo:
porre nella “Document Root” $cfg['Servers'][$i]['auth_type'] = ”http”
del server Apache (ossia dove
finora abbiamo posto le nostre A questo punto apriamo il
pagine PHP per verificarle off-li- nostro browser preferito e scri-
ne, la cartella dove il nostro viamo l'indirizzo dove è instal-
server va a leggere quando sul- lato phpMyAdmin: sarà qual-
la barra dell'indirizzo scrivia- cosa del tipo http://127.0.0.1/
mo, ad esempio, http://lo- phpMyAdmin.
calhost o http://127.0. 0.1). Si aprirà una finestra di ri-
Per far funzionare phpMyAd- chiesta di accesso. Indicando
min entriamo nella cartella di user e password (quelle di root
installazione tramite Gestione o quelle di un utente preceden-
Risorse e apriamo, con un qual- temente creato) avremo acces-
siasi editor di testo, il file con- so al pannello di controllo (im- Il pannello di controllo di PHPMyAdmin

5 L’integrazione fra MySQL e PHP


bbiamo imparato a co- siamo certo pretendere che tut- zionamento nel caso l'archi- La prima cosa da fare è con-

A struire un database par-


tendo da schemi puramen-
te concettuali per arrivare allo
ti imparino il linguaggio SQL
per interrogare un database,
anche perché comunque do-
tetto del DB sia un'altro pro-
fessionista;
• interrogare il database utiliz-
nettersi al database.

Connessione al server
schema logico generale e infine vremmo prima spiegare loro gli zando SQL; MySQL
all'implementazione fisica al- schemi alla base della costru- • utilizzare i record risultato È piuttosto semplice effet-
l'interno del Relational DBMS zione della base di dati. per comporre informazioni tuare la connessione al server
scelto per ospitare i dati. Siamo Risolvere questi problemi e/o pagine Web; MySQL che ospita il nostro da-
in grado di popolare il database equivale a fare l'ultimo passo • fornire un facile sistema di ge- tabase Universitas. Sono ri-
e di gestire aggiornamenti, can- verso l'ambiente “globale” de- stione al web content. chiesti tre parametri: indirizzo
cellazioni e interrogazioni an- scritto nella lezione 3 e quindi del server MySQL, user e pas-
che di una certa complessità. creare un completo Database PHP è un linguaggio forte- sword di un utente (root o al-
Il problema è che solo noi System. Per fare questo dob- mente votato al connubio con tro):
siamo in grado di farlo, e co- biamo unire le potenzialità di un database e può dare una mysql_connect (server, user,
munque non è sempre facile ri- PHP a quelle di MySQL, allo marcia in più al Web. PHP, inol- password);
cordare tutti i passaggi. Ma se scopo di creare delle soluzioni tre, non è “sposabile” solo con
ci fossero, ed è assolutamente user-friendly di gestione del da- MySQL: potremo altrettanto fa- In caso di successo la fun-
normale sia così, altre persone tabase. Nel caso particolare del cilmente usarlo per interfac- zione restituisce un identifica-
coinvolte nella gestione della nostro corso, il Web developer ciarci con database come DB2, tivo di connessione che ri-
base di dati? E se dovessimo PHP dovrà essere in grado di: Firebird, MSSQL, Oracle, Post- marrà invariato fino alla chiu-
usare i dati “grezzi” estratti da greSQL, Sybase e anche, trami- sura della stessa, mentre in ca-
MySQL per fornire informazioni • creare un database efficiente te i driver ODBC, con Microsoft so negativo viene restituito un
a degli utenti esterni? Non pos- o comunque capirne il fun- Access. valore false.
4a lezione

Effettuata la connessione al
server, si deve indicare su qua- listato connessione_prima.php
le database vogliamo agire. <?php //Creo una connessione con il database universitas
Con l'interfaccia a caratteri si $nome_db = "universitas"; $id_connessione=@mysql_connect("127.0.0.1","root","pluto") or die("Non è possibile
usava il comando use, mentre accedere al server");
con PHP utilizziamo: // mysql_connect apre la connessione al server, e mysql_select_db la sfrutta per accedere ad uno specifico database
mysql_select_db (nome_db, @mysql_select_db($nome_db,$id_connessione) or die(“Non è stato possibile accedere al database”);
identificativo di connessione); ?>

Il risultato sarà un valore


true o false (se il DB non esiste
o se non si è riusciti ad effet- listato query_uno.php
tuare la connessione al server), $q="SELECT nome, cognome, matricola, date_format(data_nascita,'%d-%m-%Y') AS data FROM studente ORDER BY
e nel primo caso il database cognome, nome";$id_ris=@mysql_query($q) or die("Non è possibile eseguire la query");
scelto sarà attivo per tutte le // mysql_query restituisce un identificativo di risorsa. mysql_fecth_array estrae come array la prima riga del risultato della
prossime azioni. query. Con un ciclo while estraggo tutte le righe della query. Uso o chiavi numeriche o chiavi corrispondenti ai nomi usati
Per connetterci al database nella select
universitas del nostro server
locale (come utente root) pos- while ($record=mysql_fetch_array($id_ris)) {
siamo scrivere un file PHP co- echo "Matricola: ".$record[matricola]."<br>$record[1] $record[0] - data di nascita: ".$record[data]."<p>";
me quello visibile nel codice }
sorgente della pagina connes-
sione_prima.php. La pagina ci
dice se siamo connessi al data- listato query_due.php
base universitas, e in caso di $q="SELECT nome, cognome, matricola, date_format(data_nascita,'%d-%m-%Y') AS data FROM studente ORDER BY
errore (provate ad esempio a cognome, nome";
bloccare il server MySQL o a $id_ris=@mysql_query($q) or die("Non è possibile eseguire la query");
cancellare il database universi- $numero_righe=mysql_num_rows($id_ris);
tas) stampa una riga di scuse echo "Gli studenti presenti nel DB sono $numero_righe<p>";
invece del messaggio di errore. mysql_data_seek($id_ris,$numero_righe-1);
Le righe di connessione sono // mysql_data_seek sposta il puntatore del risultato all'ultimo record, e mysql_fetch_array estrae un array
visibili nel listato connessio- corrispondente a questa posizione
ne_prima.php. $record=mysql_fetch_array($id_ris);
Le connessioni mysql_con- echo "Ecco l'ultimo studente presente nel database:<br>Matricola:
nect (non persistenti) restano ".$record[matricola]."<br>$record[1] $record[0] - data di nascita: ".$record[data]."<p>";
aperte fino alla chiusura della
pagina oppure fino alla chia-
mata della specifica istruzione funzione chiuderà l'ultima connessione mandi SQL e inoltre fornisce Un identificativo di risorsa
che chiude la connessione in- aperta una serie di utili funzioni con le può essere passato come argo-
dicata o comunque l'ultima quali possiamo interrogare il mento alla funzione mysql_fet-
aperta: Interazione PHP-MySQL server, interagire con esso e ch_array la quale carica tutti i
mysql_close(); La libreria MySQL di PHP valutare le prestazioni del da- campi del primo record del ri-
// essendo senza argomenti, la consente di inviare query e co- tabase. sultato in un array.
L'istruzione fondamentale è Per richiamare i valori del-
13 mysql_query: grazie ad essa l'array possiamo fare riferi-
possiamo inviare una query al mento alla solita chiave nume-
database attivo (o specificare rica (il primo elemento ha
una connessione diversa). chiave zero) oppure usare co-
Chiaramente mysql_query ci me chiave il nome del campo
consentirà di effettuare sul da- dedotto dalla query. Una suc-
tabase solo operazioni coeren- cessiva chiamata alla stessa
ti col nostro profilo utente. funzione mysql_fetch_array
La tipica costruzione di una caricherebbe il secondo re-
query in PHP è: cord, e così via fino a raggiun-
$q = “SELECT * FROM studente”; gere l'ultimo record dopo il
$ris = mysql_query ($q); quale verrebbe restituito un
valore false. Un ciclo while,
Il valore di $ris può essere: quindi, è perfetto per consen-
• false in caso di errore: la tirci di recuperare tutti i re-
query potrebbe essere erra- cord di una qualsiasi query di
ta; selezione (listato
• un identificativo di risorsa se query_uno.php), come si può
la query è del tipo SELECT, vedere aprendo la pagina
SHOW, EXPLAIN o DESCRIBE. query_uno.php che elenca gli
In questo caso nulla viene studenti presenti nel DB (im-
detto sul risultato ottenuto magine 13).
(ad esempio non si sa il nu- Se volessi recuperare il ri-
mero di righe restituito); sultato di una riga ben specifi-
• true in tutti gli altri casi: ad ca, ad esempio l'ultima, dovrei
esempio con UPDATE, DELE- usare altre due funzioni: my-
il risultato di una query SQL recuperato con istruzioni PHP TE, DROP TABLE, ecc. sql_num_rows che estrae il 
4a lezione

 numero di righe risultanti dalla


query, mentre mysql_data_ listato stud_select.php
seek sposta il puntatore del ri- <select name="stud_nome">
sultato ad una riga indicata nei <?php
suoi attributi (in questo caso while ($record=mysql_fetch_array($id_ris)) {
la riga sarà l'ultima). L'utilizzo echo "<option value=".$record[matricola].">".$record[0]."</option>";
sarà chiarito dal seguente }
esempio (listato mysql_close();
query_due.php): ?>
Se vogliamo dare maggiore </select>
interattività alle nostre pagi-
ne, possiamo iniziare con un
esempio utile e semplice: sele-
zionare da una casella a disce- listato stud_cv.php
sa uno studente inserito nel // Terza operazione: se lo studente è in tesi, stampare i dati del professore che lo segue
database per ricavare tutte le if (!is_null($record_1[tesi_con])) {
informazioni su di lui (anni, $q_3="SELECT prof.cognome AS cognome, prof.nome AS nome, prof.dipartimento AS dipartimento FROM prof,studente
esami sostenuti, media, se è in WHERE studente.matricola='".$record_1[matricola]."' AND prof.cod_fisc=studente.tesi_con";
tesi con qualche professore). $id_ris_3=@mysql_query($q_3) or die("Non è possibile eseguire la query");
Costruiamo due pagine: la pri- $record_3=mysql_fetch_array($id_ris_3);
ma servirà alla selezione dello echo "<h3>Lo studente è in tesi col prof. ".$record_3[cognome]." ".$record_3[nome]." del Dipartimento di
studente (stud_select.php), ".$record_3[dipartimento]."</h3>";
mentre nella seconda “stam- }
peremo” la sua scheda
(stud_cv.php). La query della
prima pagina assomiglia a
quanto visto nel listato listato voto_gestione.php
query_uno.php, però abbiamo if (isset($_POST['inserisci'])) {
concatenato tre campi (matri- $q_3="INSERT INTO esame VALUES ('".$_POST['stud_nome']."','".$_POST['stud_es']."','".$_POST['voto']."',
cola, cognome e nome). Nel '".$_POST['lode']."','".$_POST['data']."')";
tag “select” del form passere- mysql_query($q_3);
mo questo campo come valore if (mysql_affected_rows()==1) echo "Il voto è stato inserito";
da visualizzare, ma alla scelta else echo "Attenzione: il voto non è stato inserito perché lo studente selezionato ha già sostenuto quell'esame";
fatta corrisponderà il valore }
della matricola che è il campo elseif (isset($_POST['elimina'])) {
chiave (listato $q_4="DELETE FROM esame WHERE matricola='".$_POST['stud_nome']."' AND cod_corso='".$_POST['stud_es']."'";
stud_select.php). mysql_query($q_4);
Selezionato lo studente, nel- if (mysql_affected_rows()==1) echo "Il voto è stato cancellato";
la seconda pagina si tratta so- else echo "Attenzione: il voto non è stato cancellato perché non era mai stato inserito prima";
lamente di far eseguire al ser- }
ver MySQL, tramite PHP, alcu-
ne query con join: il listato
stud_cv.php riprende solo una L'ultimo esempio (file vo- eliminare) un esame svolto da cancellazione del record (at-
delle tre query previste (si ri- to_gestione.php) riguarda l'in- uno studente. La pagina con- tenzione all'uso “compatto”
manda al file per il codice serimento e la cancellazione terrà un form con due pulsan- degli if interni). Si lascia al let-
completo). Il risultato, con dei dati dal nostro database. A ti per inserire o cancellare la tore la rifinitura della funzio-
una formattazione di massima, tale scopo predisponiamo una votazione. Notate le due casel- ne, ad esempio per impedire
è visibile nell'immagine 14. pagina dalla quale inserire (o le a discesa di selezione: ser- di effettuare un inserimento
vono a preservare l'integrità se il voto non è stato scritto
14 referenziale del database, im- nel form, o impedire di asse-
pedendo di inserire nella ta- gnare la lode ad un voto mino-
bella “esame” una matricola re di 30.
non esistente o un corso non Con questa doverosa intro-
attivato. duzione sul rapporto tra PHP
Chiaramente se si tentasse e MySQL si chiude anche la
di inserire un voto di un esame quarta puntata del corso. La
già sostenuto non si otterreb- prossima sarà totalmente de-
be alcun risultato perché sa- dicata ad approfondire esempi
rebbe una violazione della pratici di applicazioni PHP-My-
chiave della tabella. Per il con- SQL e vedremo come gestire
trollo usiamo la funzione my- in tutte le sue parti un sito
sql_affected_rows che resti- Web dinamico.
tuisce il numero di record in-
teressati dalla query: se il va- Approfondimenti:
lore ottenuto è zero significa
che si è cercato di inserire un http://www.mysql.com
voto che già c'era o di cancel- http:/www.mysql.com/documentation
lare un voto che non esisteva. http://www.mysql.com/downloads
Il listato voto_gestione.php fa http://www.php.net/mysql
vedere il particolare delle http://www.phpmyadmin.net
La scheda dello studente selezionato istruzioni di inserimento o http://www.easyphp.org
5a lezione

 A scuola con PC Open

Web Developer PHP di Federico Pozzato

1 La gestione di un sito dinamico


e quattro lezioni pubblicate un po' di teoria dei database, do loro un taglio ancora più sto portale espan-

L del corso “Web Developer


PHP” ci hanno insegnato le
basi del linguaggio PHP, basi
dal momento che uno svilup-
patore non può essere digiuno
di un aspetto sempre più fon-
pratico ed esemplificativo: lo
scopo finale, infatti, è creare un
completo portale Web di com-
dibile fin da subito.
L'esempio, capi-
ta la logica di fon-
necessarie per sviluppare un damentale nell'evoluzione del menti tematici, comprensivo do, potrà poi essere I listati
sito dinamico utilizzando come Web. di una zona protetta di ammi- usato come spunto completi
DBMS il database open-source Quest'ultima lezione riuni- nistrazione e gestione. La sfida per Web site più sono sul CD
MySQL. Abbiamo visto anche sce molti dei concetti visti dan- più interessante è rendere que- complessi.

2 Progettare un sito Web di notizie e commenti


nnanzitutto per lavorare al fici di loro interesse. Il portale IL CALENDARIO DELLE LEZIONI
I meglio dobbiamo avere chiari
i punti di partenza e di arrivo
del progetto che ci apprestia-
deve essere assolutamente
semplice e fruibile in maniera
immediata da parte dell'utente, Lezione 1: Lezione 4:
mo a realizzare. che in pochi attimi deve riusci- - PHP con un server off line - PHP e MySQL
L'obiettivo (il goal) è la crea- re a individuare la sua area di - Funzioni base e variabili - MySQL, database
zione di un sito nel quale inse- interesse e a leggere i commen- - I costrutti di controllo opensource
rire articoli, opinioni e ap- ti inseriti. - Costruzione e interrogazione
profondimenti (in generale: Si deve anche prevedere un Lezione 2: di un database: il linguaggio
commenti) su una o più macro minimo di interattività, dando - Approfondiamo PHP SQL
aree, a loro volta suddivise in ai visitatori la possibilità di scri- - Include e require - Interfaccia GUI: PhpMyAdmin
argomenti: le aree (l'object), ad vere le proprie opinioni e di - Funzioni e classi - Integrazione MySQL e PHP
esempio, potrebbero essere la iscriversi ad una mailing list. - Proteggere una pagina
letteratura, il cinema, la politi- Gli articoli saranno affidata a - Cookie e sessioni  Lezione 5:
ca, l'ambiente e via dicendo. più persone (“giornalisti”), - La funzione mail - La gestione di un sito
Inizialmente si partirà con esperte nel loro campo. Queste dinamico
un paio di aree (ambiente e persone operano da luoghi di- Lezione 3: PHP e i database - Il sito Web da sviluppare
informatica), da incrementare versi (anche da casa), quindi - La funzione upload - Il compito del WebDeveloper
in seguito. Il sito si rivolgerà (il deve essere predisposto un si- - Lavorare con i file - Il database
target) a visitatori desiderosi di stema Web grazie al quale pos- - La gestione degli errori - La struttura del sito
approfondire argomenti speci- sano inserire i loro scritti nel - Accenni di sicurezza - La costruzione del sito:
portale dopo una autenticazio- - Il database system la parte pubblica
1 ne di accesso. - Siti Web dinamici - La costruzione del sito:
Bisogna poi prevedere un - Teoria dei database le pagine di gestione
COMMITTENTE UTILIZZATORI amministratore unico del sito, i
cui compiti principalmente sa-
ranno: • gestire i testi di presentazione In termini progettuali, quan-
BRIEFING • convalidare o cancellare com- delle pagine. to scritto nelle righe preceden-
menti e foto inseriti dai gior- C'è un vincolo (un manda- ti rappresenta il briefing (vedi
nalisti; tory) importante: sia i giornali- figura 1) del compito assegna-
WEB DEVELOPER • inserire, modificare e cancel- sti che l'amministratore sono toci: “to brief”, infatti, significa
lare le macro aree e gli argo- utilizzatori Web, ma non sanno riassumere, dare istruzioni a
menti (in accordo con l'edito- nulla di HTML, PHP, SQL o da- qualcuno. Mancherebbero un
re del sito); tabase. Va quindi fornito un paio di dettagli fondamentali
REALIZZAZIONE • aggiungere, modificare o eli- portale “chiavi in mano”, sem- come il tempo di realizzazione
minare i giornalisti; plice e pronto all'utilizzo anche (il timing) e i soldi a disposi-
Il ciclo di realizzazione di un
progetto Web • gestire la mailing list e spedi- per quanto riguarda la gestio- zione (il budget), ma per il no-
re la newsletter; ne. stro esempio sono irrilevanti.
5a lezione

3 Il compito del Web Developer


l primo briefing seguirà Partendo da questo punto, mail e uno per iscriversi alla se sviluppato: la difficoltà, a

A poi un lavoro ciclico di


chiarimento (non sempre
è possibile realizzare quello
stabiliamo una via di sviluppo,
tra le tante possibili, per la par-
te pubblica del portale.
mailing list (o cancellarsi).
La pagina principale, quella
che conterrà la cosiddetta “bi-
questo punto, è solo di pro-
grammazione SQL.
Vi sono poi altre due pagine
che il cliente vorrebbe alle sue L'home page dovrà presen- blioteca dei commenti”, avrà “accessorie”:
condizioni), al termine del qua- tare brevemente il sito, spie- differenti tipi di visualizzazione • scrivici: consente di spedire
le il Web Developer sarà pronto garne l'obiettivo e dare delle in- dipendenti dalle scelte effet- commenti sul sito;
a realizzare il sito unendo, se dicazioni di navigazione. I testi tuate nella pagina stessa o nel- • mailing list: consente di in-
necessario, le sue competenze saranno scritti dall'ammini- la home page. Si potrà, infatti, serire la propria mai per rice-
con quelle di altri professioni- stratore del sito e potranno es- visualizzare (scegliendo uno vere la newsletter o per can-
sti Web. Per semplicità assu- sere modificati in qualunque dei due ordinamenti possibili) cellare l'iscrizione.
meremo di essere in grado di momento. Servirà poi una se- tutto l'elenco dei commenti, Le pagine saranno dinami-
creare il sito da soli. zione dalla quale accedere alla oppure l'elenco dei commenti che, nel senso che la loro mo-
Viste le premesse e i vincoli lista generale dei commenti, or- di un'area o di un suo argo- difica sarà determinata diretta-
di progetto, è chiaro che dovre- dinati in due modi: per numero mento, oppure vedere il com- mente dagli aggiornamenti del
mo sviluppare un portale dina- di click o per data di inseri- mento stesso comprensivo di database e non da modifiche di
mico utilizzando un DBMS co- mento. Terzo punto da realiz- immagini. In ogni caso, questa codice sui listati HTML e PHP.
me MySQL e integrandolo con zare sarà l'elenco di tutte le pagina dovrà prevedere una A noi basterà quindi creare il
il linguaggio PHP. Predisporre- aree e dei relativi argomenti, barra di navigazione per poter- template della pagina senza oc-
mo due differenti profili di ac- con link cliccabili. Per ogni si spostare tra le pagine del si- cuparci dei contenuti e del loro
cesso alla gestione del databa- area, inoltre, prevediamo di in- to e un menu grazie al quale cambiamento.
se per amministratore e giorna- serire due link diretti al com- scegliere il tipo di visualizza- La parte amministrativa sarà
listi, realizzando per loro un'ap- mento più letto e all'ultimo zione e il tipo di ordinamento. creata tenendo presente la ne-
posita interfaccia grafica Web commento inserito. È chiaro Ulteriore attenzione va posta cessità di stabilire due diffe-
di gestione. Escludiamo di dare che questa terza parte sarà to- all'elenco dei commenti: per renti profili per amministratore
a queste persone accesso di- talmente gestita dal database: evitare che diventi troppo lun- e giornalisti. Il primo avrà ac-
retto al client MySQL (sia esso una volta scritto il codice della go (e quindi poco fruibile) use- cesso a tutte le parti configura-
grafico o a caratteri), per moti- pagina non dovremo più preoc- remo delle sottopagine, visua- bili del database, mentre chi
vi di praticità (le persone coin- cuparci di fare nessun aggior- lizzando i dati sintetici di 5 scrive gli articoli avrà un ac-
volte sono solo utilizzatori del namento. In calce alla home commenti per ogni sottopagi- cesso che gli consentirà solo di
Web) e anche per motivi di si- page, infine, ci saranno i link a na. Questa pagina è completa- inserirli nel sistema e modifi-
curezza (mai da sottovalutare). due form: uno per scrivere una mente gestita grazie al databa- carli (immagini comprese).

4 Il database
a prima operazione da cettuale Entità-Relazione (vedi mo una gestione che non ne- temente dalla struttura definita

L compiere, quella che poi


necessariamente guiderà la
realizzazione delle pagine, è la
figura A), da trasformare suc-
cessivamente in uno schema
logico relazionale normalizza-
cessita di una tabella. Neppure
l'amministratore è inserito nel-
lo schema perché non sono de-
per il DB.
Queste tabelle sono:

definizione della struttura della to. Le entità non sono molte: i finite relazioni con altre Entità: • amministrazione: nome (chiave),
base di dati da realizzare. commenti, le aree, gli argo- chi amministra, infatti, sovrin- user, password, e-mail
Come visto nella lezione 3, si menti e i giornalisti. Non ci so- tende tutte le attività e pertan- • mailing: nome, e_mail (chiave)
deve definire uno schema con- no le immagini: per loro usere- to non è legato direttamente a • testi_admin: id_testo (chiave),
nessuna. descrizione, testo
A Dallo schema concettuale
deriva lo schema logico (figura Costruire il DB è un ottimo
1 N B) in cui è indicata la composi- esercizio (lezione 4), comun-
Giornalista scrive Commento zione di ogni tabella. I campi que nel CD allegato alla rivista
N chiave sono in grassetto, men- è presente il file commenti.sql
tre i campi con l'asterisco rap- che contiene la struttura com-
presentano una colonna che, pleta del database e alcuni da-
su pur non essendo chiave, con- ti di esempio. Aprendo il file
tiene solo valori numerici unici con un editor di testo si può ve-
ed è quindi utilizzabile come ri- dere nel dettaglio la struttura
1 ferimento esterno per altre ta- ed i tipi di dato di ogni tabella.
N 1 belle. Nello schema finale man- Se scegliamo di caricare il fi-
Argomento appartiene Area cano alcune tabelle che, pur fa- le, creiamo prima il database
cendo parte del database, pos- Commenti, quindi importiamo
siamo definire di servizio gene- struttura e dati usando gli ap-
Lo schema Entità-Relazione del database Commenti rale al sito e sono quindi dota- positi comandi di PhpMyAd-
te di vita propria indipenden- min (vedi immagine 1 e imma- 
5a lezione

 gine 2). Usando il client a ca- B


ratteri di MySQL scriviamo in- COMMENTO
vece dalla shell DOS (dalla car- GIORNALISTA
tella c:\mysql\bin): id_commento
1 N
id_giornalista id_giornalista ARGOMENTO
mysql -u root -p nome id_argomento
// inseriamo la password per entrare user N 1
titolo id_argomento* AREA
nel client password testo argomento
mysql> CREATE DATABASE commenti; desc data_ins N 1
id_area id_area*
mysql> EXIT e-mail pubblicabile
// siamo usciti dal client mysql area
data_inizio click
mysql -u root -p commenti < attivo
commenti.sql
// eventualmente scrivere il percorso Schema logico relazionale del database Commenti
assoluto del file commenti.sql

1 2

Creiamo il database Commenti Azioni per importare struttura e dati nel database Commenti

5 La struttura del sito


nnanzitutto vediamo il signi- due icone e la pagina che ci re-

I ficato delle cartelle presenti


nella root del portale :
stituisce i parametri del parser
PHP installato (nel caso ci ser-
visse controllare i settaggi di
<?php
$nome="commenti";
$id_connessione=@mysql_connect('127.0.0.1','root','pluto') or
• nella root c'è solo l'home PHP; die('Non è possibile accedere al database');
page “index.php” dalla quale • le cartelle “admin” e // dati connessione: user=root, password=pluto, indirizzo
la navigazione ha inizio. È sem- “giorn” servono per la gestione server=127.0.0.1, nome database=commenti
pre buona norma lasciare solo delle aree protette riservate ad @mysql_select_db($nome,$id_connessione) or die("Non è
l'home page nella root; amministratore e giornalisti; stato possibile accedere al database");
• la cartella “pagine” ospita • la cartella “img” contiene ?>
le pagine che ci consentono di le immagini caricate per illu- Listato 1: servizi/conn.php
vedere i commenti, spedire strare meglio i commenti. Que-
una mail, iscriverci alla mailing sta cartella dovrà avere i per-
list. Sono le pagine “pubbliche” messi di scrittura abilitati in Il file commenti.css (vedi una essere i colori, i caratteri, le di-
del sito; modo da poter effettuare un piccola parte nel listato 2, con mensioni e via dicendo). È un
• la cartella “servizi” ospita i upload da una pagina Web. lo stile applicato per il tag tipico foglio di stile e ci facilita
dati della connessione, il foglio Vista la loro importanza ge- body) ospita invece le defini- nella scrittura della pagina e
di stile responsabile del layout, nerale, guardiamo due pagine zioni delle formattazioni usate nella gestione delle opzioni di
contenute nella cartella “servi- nel sito (tipici esempi possono layout.
NB: le pagine del sito si zi”.
trovano tutte all'interno della Il file conn.php (listato 1)
cartella CD2/PDF/Corsi/PHP/ contiene le impostazioni della body {
lezione_5/commenti nel CD connessione al server MySQL background-color: #FFFF99;
Guida 2 che è la radice (root) (lezione 4) che ospita il data- font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
del sito. base “commenti”. Chiaramente font-size: 11px;
Ad essa si farà sempre questa pagina deve sempre es- width: 750px;
riferimento indicando il sere “inclusa” nelle altre prima }
percorso relativo della pagine di effettuare qualsiasi tipo di Listato 2: servizi/commenti.css
operazione sulla base di dati.
5a lezione

6 La costruzione del sito: la parte pubblica


home page “index.php” 3 riferiti a tutti gli argomenti del-

L' (immagine 3) sarà com-


posta da:
• tre testi editabili dall'ammini-
l'area. Notiamo la presenza (li-
stato 5) nella query $sql_2 di
un join (legame tra una o più ta-
stratore del sito. I testi sono belle che fanno riferimento le
quelli visibili su sfondo giallo; une alle altre. Vedi lezione 4): la
• una sezione “testi commenti” clausola WHERE, infatti, lega i
che consente di vedere tutti valori dell'identificativo dell'a-
gli articoli “pubblicabili” pre- rea della tabella “area” e della
senti nel database; tabella “argomento”. I link con-
• N sezioni tante quante sono tengono una nuova variabile
le aree trattate (nel nostro GET di nome “arg” che ha co-
caso sono due, ambiente e me valore l'identificativo uni-
informatica): per ogni area voco dell'argomento.
sarà presente l'elenco degli
argomenti e due link veloci al- $sql_2=
l'ultimo articolo inserito e al- "SELECT argomento.testo_argomento
l'articolo più letto; AS testo, argomento.id_argomento
• un'ultima sezione in basso AS id FROM argomento,area WHERE
coi link per scrivere i propri argomento.id_area=area.id_area AND
commenti al sito o per acce- area.id_area='".$tab_1[id_area]."'
dere alla mailing list. ORDER BY
Per visualizzare i tre testi argomento.testo_argomento";
scriveremo una query e memo- $ris_2=mysql_query($sql_2);
rizzeremo i risultati su un array echo "<span class='normale'>
Home page del portale dei commenti
$home da richiamare nei punti Argomenti: </span>";
opportuni della pagina (listato while ($tab_2=mysql_fetch_array
3). Avremmo anche potuto testi_admin corrisponde utilizzando questo codice scri- ($ris_2)) {
scrivere tre query diverse per all'identificativo 'home_p' veremo una seconda query che // scrivo i link a tutti gli argomenti di
estrarre ogni volta il valore del echo $home[home_p]; estrarrà, dalla tabella “argo- quell'area
testo voluto, ma con la soluzio- ?> mento”, gli argomenti che si ri- echo "<a href='pagine/commenti.php
ne scelta si fa una sola richiesta listato 3: index.php fanno ad esso. Una terza e una ?arg=".$tab_2[id]."' class='arg'>".
al server. I testi sono memoriz- quarta query, infine, sempre $tab_2[testo]."</a> | ";
zati nella tabella di servizio “te- La sezione “testi commenti” usando il codice dell'area, ci }
sti_admin” e hanno la peculia- contiene solo istruzioni HTML consentiranno di scrivere i link listato 5: index.php
rità di contenere la stringa “ho- perché è sempre fissa: cliccan- all'ultimo commento inserito e
me_” nell'id_testo che li defini- do sul titolo si accede alla pa- al più letto. La terza query $sql_3 (lista-
sce univocamente. Per sfrutta- gina commenti.php visualizzan- La prima query $sql_1 è or- to 6) e la quarta $sql_4 estrag-
re questa particolarità utiliz- do i commenti in ordine decre- dinata in base al nome dell'a- gono un solo record dalla ta-
ziamo la clausola LIKE nella scente di data di inserimento, rea: introduciamo nel tag <a> bella “commento”: rispettiva-
query SQL: LIKE consente di fa- mentre cliccando sul link nel del link una nuova variabile mente il codice e il titolo del-
re delle ricerche su stringhe di prosieguo del testo si visualiz- GET di nome “area” il cui valo- l'ultimo commento inserito e
testo e il carattere di percen- zano gli articoli dal più letto al re sarà l'identificativo univoco del più letto. Ovviamente il
tuale “%” indica il carattere jol- meno letto. In questo secondo dell'area (listato 4). Grazie a commento deve appartenere
ly. L'array $home memorizzato caso avremo l'accortezza di in- questa variabile cliccando sul all'area selezionata ed essere
in questo modo ha la caratteri- serire nell'indirizzo del link una link visualizzeremo solo i com- stato definito “pubblicabile”
stica di avere come chiave l'i- variabile di tipo GET (lezione menti di quell'area. dall'amministratore. Il link di-
dentificativo del testo che si 1) di nome 'ord' e di valore retto al commento è reso pos-
vuole stampare e come valore 'plus': $sql_1="SELECT id_area,testo_area sibile dalla presenza della va-
il testo stesso. È quindi sempli- FROM area ORDER BY testo_area"; riabile GET di nome “comm”
ce visualizzare il testo voluto // link ai commenti ordinati per data $ris_1=mysql_query($sql_1); che ha come valore l'identifica-
con una istruzione echo (ne decrescente while ($tab_1=mysql_fetch_array tivo univoco del commento:
compariranno quindi tre in <a href="pagine/commenti.php" ($ris_1)) {
questa home page). class="tema">Tutti i commenti</a> // per ogni area estratta inserisco il $sql_3="SELECT commento.titolo,
// link ai commenti ordinati dal più al link dell'area stessa e scrivo una argomento.testo_argomento,
<?php meno letto query per ricavare gli argomenti relativi commento.id_commento FROM
// estraggo le descrizioni della home <a href="pagine/commenti.php? all'area commento,argomento WHERE
page e le salvo nell'array $home per ord=plus" class="arg">commenti echo "<div class='tem'><a href= commento.pubblicabile='si' AND
usare poi la descrizione dove serve più letti</a> 'pagine/commenti.php? commento.id_argomento=argomento.
$sql="SELECT id_testo, testo FROM area=".$tab_1[id_area]."' id_argomento AND
testi_admin WHERE id_testo LIKE Più complesso è visualizzare class='tema'>".$tab_1[testo_area]." argomento.id_area='".$tab_1
'home_%'"; ogni singola area con i relativi </a> [id_area]."' ORDER BY
$ris=mysql_query($sql); argomenti e link ai commenti. listato 4: index.php commento.data_ins DESC LIMIT 0,1";
while ($tab=mysql_fetch_array($ris)) { Dovremo usare delle query ni- $ris_3=mysql_query($sql_3);
$home[$tab[id_testo]]=$tab[testo]; dificate: con la prima estrarre- La seconda query, nidificata $tab_3=mysql_fetch_array($ris_3);
} mo nome e codice di ogni re- nel ciclo while della query pre- echo "<p><span class='normale'>
// visualizzo il testo che nella tabella cord dalla tabella “area”, poi cedente, serve a scrivere i link Ultimo articolo inserito: </span> 
5a lezione

 <a href='pagine/commenti.php? zione (il nome della pagina in in un array $list che ha come stro caso la precedenza è dal-
comm=".$tab_3[2]."' class='art'>". cui ci troviamo sarà scritto in chiave l'identificativo univoco l'alto in basso:
$tab_3[0]."</a>&nbsp;<span grassetto e non sarà cliccabi- dell'argomento e come valore il • $_GET[comm]=x : verrà vi-
class='normale'>[".$tab_3[1]."] le). conteggio appena fatto. Sfrut- sualizzato (testo e immagini)
</span>"; Il menu di navigazione a si- tando questo vettore posso ri- il commento avente identifi-
listato 6: index.php nistra segue la logica vista nel- cavare anche quanti commenti cativo x;
la costruzione della home pa- ci sono in ogni area (creo il vet- • $_GET[arg]=y : visualizzazio-
Ultima annotazione: l'estra- ge. Le differenze riguardano tore $tot_area) facendo una ne della lista dei commenti
zione di un solo record è con- l'aggiunta, a fianco di ogni scrit- semplice somma durante il ci- che fanno parte dell'argo-
sentita dalla clausola LIMIT ta, di una icona col segno “+” e clo while che visualizza gli ar- mento di codice y;
presente nel codice SQL: del numero di commenti con- gomenti di ogni area. I valori • $_GET[area]=z : visualizza-
tenuti in ogni argomento. Clic- appena ricavati serviranno poi zione della lista dei commen-
LIMIT (X,Y) cando sull'icona + si ottiene la per creare le sottopagine di ti che fanno parte dell'area di
lista dei commenti ordinata ogni scelta. Sommando tutti i codice z;
Questa clausola limita il ri- dall'articolo più letto al meno valori dell'array (con la funzio- • nessuna della variabili prece-
sultato ottenuto dall'esecuzio- letto: questo è reso possibile ne PHP array_sum) posso an- denti: viene visualizzata la li-
ne della query, estraendo Y re- dall'aggiunta della variabile che ottenere il numero totale di sta completa dei commenti.
cord a partire dalla posizione X GET di nome “ord” e valore documenti pubblicabili pre- Altre due variabili possono
dei record estraibili. “plus” nel riferimento del link. senti nel database. trovarsi nell'URL e sono affian-
La pagina “biblioteca dei Cliccando sulle scritte, invece, cate alle precedenti:
commenti” (file pagine/com- questa variabile non è presente // conto quanti record ci sono • $_GET[pg]=w : viene visua-
menti.php, immagine 4) sarà in- e si otterrà una lista ordinata raggruppandoli per id_argomento, e lizzata la sottopagina w (se
vece composta da: per data di inserimento decre- registro il numero nel vettore $list non c'è vuol dire che non ci
• una barra di navigazione per scente. Ecco i due link a con- sono sottopagine);
spostarsi tra le pagine; fronto: $sql_3="SELECT id_argomento, • $_GET[ord]=plus : ordina-
• un menu di navigazione divi- COUNT(*) AS num FROM commento mento dall'articolo più letto
so per aree tematiche, a loro echo “<a WHERE commento.pubblicabile='si' al meno letto.
volta suddivise per argomen- href='commenti.php?area=".$tab_1[id GROUP BY id_argomento"; Cosa succede quando nel-
ti con l'indicazione del nume- _area]."&ord=plus'><img $ris_3=mysql_query($sql_3); l'URL c'è la variabile “comm”?
ro di articoli inseriti; src='../servizi/bluplus.gif' alt='Più while ($tab_3=mysql_fetch_array Con una query estraiamo i dati
• un'area di visualizzazione: letti' title='Ordina per i più ($ris_3)) { che ci servono, quindi “stam-
cliccando sul nome di un'area letti'></a>&nbsp;&nbsp;<a $list[$tab_3[id_argomento]]=$tab_3 piamo” questi dati per visualiz-
o su un argomento si potrà href='commenti.php?area=".$tab_1[id [num]; zare l'articolo (immagine 5).
vedere la lista dei commenti, _area]."' } Può essere interessante osser-
lista limitata a 5 commenti class='tit'>".$tab_1[testo_area]."</a listato 7: pagine/commenti.php vare il codice (listato 8) per no-
per sottopagina. Se un titolo ></div>"; tare un paio di particolari. Le
attirasse l'attenzione, basterà La creazione dell'area di vi- immagini, ad esempio, posso-
cliccarci sopra per ottenere Interessante è capire come sualizzazione di destra è la par- no essere al massimo due per
la visualizzazione dell'artico- ricavare il numero di articoli di te più complessa della pagina. commento ($imm1 e $imm2) e
lo stesso, completo di even- ogni argomento. Si usa la clau- Dobbiamo infatti controllare il loro nome è legato al codice
tuali foto. sola SQL di raggruppamento l'URL della pagina per verifica- del commento (es: il commen-
Per la costruzione della bar- GROUP BY (lezione 4), rag- re se ci sono delle variabili GET to “12” può avere collegate due
ra di navigazione si rimanda al- gruppando tutti i commenti la cui presenza, col relativo va- immagini, nella cartella “img”,
la lezione 2. Il codice che con- pubblicabili che hanno lo stes- lore, determina la costruzione denominate “12_1.jpg” e
tiene la barra è nel file pagi- so argomento e operando su di della pagina. In particolare, al- “12_2.jpg”). Con la funzione “fi-
ne/testata.php: il file viene in- essi una operazione di somma cune variabili escludono la pre- le_exists” controlliamo se l'im-
cluso in ogni pagina, adattan- dei record (listato 7). Il sugge- senza di altre a seconda della magine è effettivamente pre-
dosi dinamicamente alla situa- rimento è salvare questi valori precedenza assegnata. Nel no- sente, e solo in caso positivo la
4 5

La pagina di navigazione di tutti i commenti pubblicati La visualizzazione di un articolo (con due immagini)
5a lezione

$tot=array_sum($list);
$sql_r="SELECT area.testo_area, argomento.testo_argomento, commento.titolo, giornalista.nome, commento.testo, $url="";
date_format(commento.data_ins,'%d-%m-%Y'), commento.click, giornalista.email, giornalista.descri, $ur="";
commento.id_commento FROM commento, argomento, area, giornalista WHERE commento.pubblicabile='si' AND // $url e $ur sono usati per
commento.id_commento='".$_GET[comm]."' AND commento.id_argomento=argomento.id_argomento AND completare il testo del link della
argomento.id_area=area.id_area AND commento.id_giornalista=giornalista.id_giornalista"; sottopagina. In questo caso sono
$ris_r=mysql_query($sql_r); vuoti, ma se avessimo scelto di
$tab_r=mysql_fetch_array($ris_r); visualizzare un'area o un argomento
echo "<strong>".$tab_r[0]." - <em>".$tab_r[1]."</em></strong><p><span avremmo dovuto dare loro i valori che
class='titoletto'>".$tab_r[2]."</span><br />[di ".$tab_r[3]."*]<br />"; poi consentono di mantenere il
// visualizzo le immagini solo dopo averne verificato la presenza riferimento alla selezione
$imm1="../img/".$_GET[comm]."_1.jpg"; if ($_GET[ord]==plus)
$imm2="../img/".$_GET[comm]."_2.jpg"; $url="ord=plus";
if (file_exists($imm1)) echo "<img src='".$imm1."' class='vis'>"; echo "<em>Elenco di tutti
if (file_exists($imm2)) echo "<img src='".$imm2."' class='vis'>"; i commenti:</em><br />";
echo "<br />".$tab_r[4]."<p><span class='normalemini'>Data: ".$tab_r[5]." - click: ".$tab_r[6]."<p>*: $mod=$tot%$vis;
".$tab_r[8]."</span><p>"; if ($mod==0) $pagine=$tot/$vis;
// incremento il valore dei click del commento scelto estraendo il valore attuale, aumentandolo di uno e facendo una else $pagine=(int) ($tot/$vis)+1;
query di aggiornamento if ($pagine>1) {
$cont=$tab_r[6]+1; echo "<span class='colore'>pagine:
$incr="UPDATE commento SET click='".$cont."' WHERE id_commento='".$tab_r[9]."'"; </span>";
mysql_query($incr); for ($i=1;$i<=$pagine;$i++) {
listato 8: pagine/commenti.php echo "<a href='".basename
($_SERVER[PHP_SELF])."?".$url.$_
GET[$ur]."&pg=".$i."'>$i</a> ";
visualizziamo. Con questa ge- _giornalista ".$ordine." LIMIT fault la sottopagina è una sola }
stione si può evitare di memo- ".$start.",".$vis; ed ha quindi valore uno): echo "<p>";
rizzare sul database il legame }
tra il nome dell'immagine e il La variabile $ordine indica il if(isset($_GET[pg]) AND $_GET[pg]>0) $ris_r=mysql_query($sql_r);
codice del commento. Avendo tipo di ordinamento dei record $sottopagina=$_GET[pg]; while
scelto di vedere l'articolo, inol- della query e si ricava da un ci- else $sottopagina=1; ($tab_r=mysql_fetch_array($ris_r)) {
tre, devo incrementare il valore clo if effettuato controllando il // $vis=5 è il numero di commenti da echo "<strong>".$tab_r[0]." - <em>
dei “click” ad esso riferiti (que- valore di $_GET[ord]: se è visualizzare per ogni pagina. $start è ".$tab_r[1]."</em></strong><br />
sto valore serve poi a stabilire uguale a “plus” l'ordinamento usato dall'attributo LIMIT delle query <a href='commenti.php?comm=
uno dei due ordinamenti dei si basa sui click, altrimenti l'or- $vis=5; ".$tab_r[4]."' class='cap'>".$tab_r
commenti): ciò si ottiene con dinamento si basa sulla data di $start=($sottopagina-1)*$vis; [2]."</a> [di ".$tab_r[3]."]<br/>
un'opportuna istruzione UP- inserimento: <span class='normalemini'>Data:
DATE. Un ultimo sforzo (listato 9) ".$tab_r[5]." - click:
Se invece nell'URL c'è una if (isset($_GET[ord]) AND ci consente finalmente di stam- ".$tab_r[6]."</span><p>";
variabile “arg” o “area” o nes- $_GET[ord]=='plus') $ordine= pare l'elenco e creare i link per }
suna delle precedenti (il che "ORDER BY click DESC, data_ins vedere le sottopagine. listato 9: pagine/commenti.php
vuol dire che vanno presi DESC"; Per prima cosa ci serve il to-
estratti tutti i commenti), dob- else $ordine="ORDER BY data_ins tale dei commenti $tot, e que- La pagina “scrivici” (file pa-
biamo scrivere tre query diver- DESC, click DESC"; sto valore lo ricaviamo som- gine/formmail.php) è un form
se per ricavare la lista degli ar- mando i valori dell'array $list per spedire una mail all'ammi-
ticoli. Le query sono abbastan- Per visualizzare N commenti del listato 6. Poi calcoliamo il nistratore del sito (lezione 2).
za simili, quindi esaminiamo per ogni sottopagina (in questo resto della divisione (con l'o- Compilati i campi, si apre una
quella che ci consente di vede- caso sono 5) usiamo una clau- peratore “modulo”, lezione 1): finestra (file pagine/risposta-
re tutti i commenti lasciando ai sola LIMIT nella query: $vis è il se è zero il numero di sottopa- mail.php) che ci informa del-
lettori la costruzione delle altre numero di commenti da visua- gine sarà dato dalla semplice l'avvenuta spedizione della
due (c'è solo una condizione lizzare su ogni sottopagina, divisione $tot/$vis, mentre se è mail o dell'impossibilità di spe-
WHERE da aggiungere) visto mentre $start indica da quale diverso da zero dovremo ag- dirla se anche solo un campo è
che la logica è esattamente la record partire per ricavare i 5 giungere 1 al risultato (intero) vuoto. C'è un controllo java-
stessa (si deve sempre fare un commenti. $start è dinamica, che si ottiene dalla divisione. script a monte che verifica se
join che coinvolge le tabelle nel senso che il suo valore di- Infine se le sottopagine sono nel campo mail c'è una @: va
commento, giornalista, argo- penderà dal numero di sotto- più di una faremo eseguire un benissimo usare dei controlli
mento e area): pagina sulla quale ci troviamo. ciclo for per ottenere i link con javascript che verificano i cam-
Il database ha 11 commenti l'opportuno valore assegnato pi prima di spedirli al server
$sql_r="SELECT area.testo_area, pubblicabili (2 non sono anco- alla variabile pg di tipo GET. (PHP lo fa dopo!), però tenete
argomento.testo_argomento, ra approvati), quindi avremo 3 Cliccando sul link della sotto- presente che javascript può es-
commento.titolo, giornalista.nome, sottopagine (vedi immagi- pagina, “commenti.php” viene sere disabilitato da parte del vi-
commento.id_commento, ne_04): se ci troviamo sulla pri- ricaricata (le altre variabili GET sitatore e quindi i controlli PHP
date_format(commento.data_ins,'% ma $start avrà valore 0 (il pri- restano invariate) e quindi il server-side vanno comunque
d-%m-%Y'), commento.click FROM mo record ha sempre posizio- valore $start viene ricalcolato. inseriti! Per spedire la mail
commento, argomento, area, ne 0), sulla seconda $start avrà Infine visualizzare la lista dei dobbiamo estrarre con una
giornalista WHERE valore 5, sulla terza $start avrà commenti con un ciclo while è query l'indirizzo mail dell'am-
commento.pubblicabile='si' AND valore 10. ormai un gioco da ragazzi. ministratore: ormai dovrebbe
commento.id_argomento= Il valore di $start sarà quindi essere un semplice esercizio.
argomento.id_argomento AND dipendente dalla variabile // $tot è il numero di commenti Anche quando si compila la
argomento.id_area=area.id_area AND $_GET[pg] che indica la sotto- presenti nel DB. Uso la funzione PHP pagina della mailing list viene
commento.id_giornalista=giornalista.id pagina da visualizzare (di de- di somma dei valori di un array aperta una pagina di risposta 
5a lezione

 (file pagine/rispostamailing. ('".$_POST['email']."','".$_POST 6


php) che ci informa se tutto è ['nome']."')";
andato bene (immagine 6) o mysql_query($query);
meno. Questa pagina verifica la
correttezza dei dati inseriti altrimenti viene eseguita una
(per cancellarsi basta inserire query di cancellazione:
solo la mail, per iscriversi ser- $query="DELETE FROM mailing
ve anche il nome) e “capta” il WHERE email='".$_POST['email']."'";
tasto premuto sul form: se ci si mysql_query($query)
vuole iscrivere viene eseguita In entrambi i casi viene spe-
una query di inserimento: dita una mail di conferma (è
una ottima abitudine farlo!) al-
$query="INSERT INTO mailing l'indirizzo mail inserito e al-
L’iscrizione alla mailing list è andata a buon fine
(email,nome) VALUES l'amministratore.

7 La costruzione del sito: le pagine di gestione


l sito pubblico è costruito, login (to log in = connettersi) ne $_SESSION['ok']. Se esiste, ti, l'unico record della tabella

I ma adesso bisogna gestirlo


inserendo commenti, imma-
gini, aree, argomenti, giornali-
verificheremo i dati inseriti, e
in caso di riscontro positivo
salveremo questa risposta in
verifica che il suo valore sia
“true” e in caso positivo con-
cede l'accesso alla pagina.
“amministrazione”. Verifico
che il risultato dell'interro-
gazione contenga una sola ri-
sti, testi. In poche parole va una variabile di sessione che Questo controllo serve ad ga: in questo caso è consen-
creata l'area di gestione. Nel verrà cancellata al momento evitare di reinserire i dati di tito l'accesso alla pagina e
nostro caso la situazione è an- del logout (e comunque alla autenticazione nel caso tor- viene registrato il valore
cor più complessa perché di chiusura del browser) nassimo a questa pagina da “true” per la variabile di ses-
aree di gestione dovremo Per accedere ad una pagina una delle altre pagine di am- sione “ok”, altrimenti il cari-
crearne due: una per l'ammini- protetta dobbiamo per prima ministrazione; camento della pagina è bloc-
stratore e una per i giornalisti. cosa creare un form di autenti- • se il primo controllo fallisce cato e compare un messag-
cazione (immagine 7) dei dati (ossia non c'è alcuna sessio- gio di avvertimento.
Area di gestione (file admin/index.php) compo- ne già iniziata che abbia una Chiaramente il file auth.inc.
dell'amministratore sto da due caselle di testo variabile di nome “ok” con php sarà incluso in testa ad
Tutte le pagine saranno “user” e “pwd” (listato 10): valore “true”) parte il pro- ogni pagina di amministrazio-
chiaramente protette da ac- cesso di autenticazione vero ne.
cessi indesiderati grazie ad un <form action="admin.php" e proprio. La prima verifica È da notare l'uso nella query
sistema di autenticazione ba- method="post"> controlla che i campi del $sql della funzione PASSWORD
sato su username e password. <input type="text" name="user" form esistano, quindi, dopo la quale crittografa (a 16 bit) il
Nella lezione 2 avevamo visto size="30"> username<br /> aver effettuato il collegamen- valore inserito nel form e lo
come implementare un siste- <input type="password" name="pwd" to al database, viene eseguita confronta col valore, anch'es-
ma statico di accesso memo- size="30"> password<p> la query $sql che ritornerà, so crittografato, contenuto nel-
rizzando user e password di- <input type="submit" name="invio" se i dati inseriti sono corret- la tabella. Questo serve esclu-
rettamente nella pagina Web, value="Connetti">
ma usare MySQL ci consente </form> 8
di registrare i dati su una ta- listato 10: admin/index.php
bella, rendendoli quindi facil-
mente modificabili in caso di I dati inseriti (i nostri soliti
bisogno. “root” e “pluto”) vengono spe-
La prima operazione da diti alla pagina admin/ad-
compiere, quindi, è validare min.php e lì controllati richia-
l'inserimento dei dati, propa- mando il file “admin/auth.inc.
gando poi l'accesso a tutte le php”. Questo file compie due
pagine oggetto di gestione sen- controlli (vedi listato 11):
za che si debbano reinserire i • per prima cosa avvia una
dati di autenticazione. Per fare sessione controllando se esi-
questo useremo le sessioni: al sta già la variabile di sessio-

Form di connessione alle pagine di gestione dell'amministratore Una parte delle opzioni di gestione dell'amministratore
5a lezione

9
<?php
session_start();
// dopo aver inizializzato la sessione, faccio il primo controllo per verificare se era già stata fatta l'autenticazione
if (isset($_SESSION['ok'])) {
if ($_SESSION['ok']!==true) die ("interrompi tutto");
}
// se è la prima volta che accedo in questa sessione, verifico i dati inseriti nel form
Una semplice richiesta di conferma (in
else { javascript) ci può far evitare di
if (!isset($_POST['user']) or !isset($_POST['pwd'])) { commettere errori
die("Per accedere a questa pagina devi inserire login e password");
}
// questo include mi rimanda alla pagina coi dati di connessione al database su “Approvato”, oppure torna-
include "../servizi/dati.php"; re alla pagina generale di am-
$sql="SELECT * FROM amministrazione WHERE user='".$_POST['user']."' AND pwd=PASSWORD('".$_POST['pwd'] ."')"; ministrazione senza convali-
$ris = mysql_query($sql); darlo. Nel primo caso (listato
$righe=mysql_num_rows($ris); 12) viene eseguita una query di
if ($righe==0) { aggiornamento su quel com-
// non c'era alcuna riga nella tabella che avesse quei valori di user e password mento (il valore chiave del
die ("Mi spiace, user e password non sono corrette. Controlla meglio l'inserimento"); commento è memorizzato su
} $_POST[id] che dobbiamo
elseif ($righe==1) { continuare a propagare inse-
// accesso consentito e contemporanea registrazione della variabile di sessione rendolo come valore nascosto
$_SESSION['ok']==true; anche nel form di questa pagi-
} na. In alternativa avremmo do-
} vuto salvare il valore in una va-
?> riabile di sessione), modifican-
listato 11: admin/auth.inc.php do il valore del campo “pubbli-
cabile” da 'no' a 'si', e viene an-
che mandata una e-mail all'au-
sivamente per aumentare la si- e rendere pubblicabili i com- } tore del commento, dopo aver-
curezza: anche se una perso- menti inseriti dai giornalisti. ?> ne estratto l'indirizzo mail, per
na, infatti, avesse casualmente Per far questo il form ci con- </select> informarlo che il suo articolo è
accesso alla tabella “ammini- sente di scegliere uno tra gli ar- adesso disponibile per la lettu-
strazione”, non avrebbe la pos- ticoli non ancora pubblicati Nella casella a discesa sono ra sul sito.
sibilità di recuperare la pas- grazie ad una casella a discesa visualizzati i primi 40 caratteri Cliccando su “Approvato” è
sword. Possiamo anche usare alimentata da una query: del titolo del commento, ma al- comparsa (se avete javascript
altre funzioni di crittografia co- la pagina successiva è passato attivato) una finestrella di con-
me MD5() e SHA1(). <select name="id" size="1" con la variabile $_POST[id] il ferma (immagine 9) che vi
Finalmente abbiamo acces- class="but"> valore dell'identificativo del chiede se siete sicuri della
so alla pagina generale di am- <?php commento (ossia la chiave). scelta fatta: questa finestra,
ministrazione (immagine 8, file $sql="SELECT id_commento, La pagina che si apre (non c'è utile per evitare di fare errori
“admin/admin.php”). La pagi- LEFT(titolo,40) FROM commento bisogno di reinserire i dati di dovuti alla fretta, si ottiene
na è composta da tanti form WHERE pubblicabile='no' ORDER BY amministratore perché la ses- semplicemente inserendo “on-
che rimandano a pagine in cui data_ins"; sione è già stata validata in submit” nella riga di intesta-
si compiono le azioni specifi- $ris=mysql_query($sql); precedenza) riporta l'articolo zione di un form:
che deputate al ruolo di ammi- while ($tab=mysql_fetch_array($ris)) { come verrebbe pubblicato.
nistratore. Una della azioni, ad echo "<option value='".$tab[0]."'>". L'amministratore può renderlo <form method="post"
esempio, è quella di approvare $tab[1]."</option>"; disponibile sul sito cliccando action="adminnews.php"
class="formadmin"
onsubmit="return
$approvato="UPDATE commento SET pubblicabile='si' WHERE id_commento='".$_POST[id]."'"; window.confirm('Sei sicuro?
mysql_query($approvato); Confermi la scelta?');">
echo "<span class='titoletto'>Il commento è stato approvato ed è quindi adesso disponibile sul sito Internet.
E' stata spedita una mail di conferma all'autore.</span><p>"; La pagina (file admin/ad-
// da qui in poi creo la mail automatica da mandare all'autore mincomm.php) che consente
$sql_g="SELECT commento.titolo, giornalista.email FROM commento, giornalista WHERE la cancellazione di un com-
commento.id_commento='".$_POST[id]."' AND commento.id_giornalista=giornalista.id_giornalista"; mento e delle immagini ad es-
$ris_g=mysql_query($sql_g); so collegato è molto simile alla
$tab_g=mysql_fetch_array($ris_g); precedente, salvo che la query
$to=$tab_g[1]; sarà di cancellazione e le im-
$subject="Approvazione commento"; magini, se ci sono, saranno
$object="Ciao, il tuo commento dal titolo \"".$tab_g[0]."\" è stato approvato ed è quindi disponibile da adesso nel cancellate con la funzione un-
sito internet.\n\nL'amministratore"; link (lezione 3):
$sql="SELECT email FROM amministrazione";
$ris=mysql_query($sql); $cancellato="DELETE FROM
$tab=mysql_fetch_array($ris); commento WHERE
$from="From:".$tab[email]; id_commento='".$_POST[id]."'";
mail($to,$subject,$object,$from); mysql_query($cancellato);
listato 12: admin/adminconv.php // cancello le immagini
$imm1="../img/".$_POST[id]."_1.jpg"; 
5a lezione

 // percorso e nome dell'eventuale


immagine 1 $sql="SELECT id_giornalista FROM giornalista WHERE attivo='si' AND user='".$_POST['user']."' AND
$imm2="../img/".$_POST[id]."_2.jpg"; password=PASSWORD('".$_POST['pwd']."')";
// percorso e nome dell'eventuale $ris = mysql_query($sql);
immagine 2 $tab=mysql_fetch_array($ris);
if (file_exists($imm1)) unlink($imm1); $righe=mysql_num_rows($ris);
if (file_exists($imm2)) unlink($imm2); if ($righe==0) {
die ("Mi spiace, user e password non sono corrette o non sei più inserito nel database dei giornalisti.
Le pagine che consentono di Controlla meglio l'inserimento");
inserire nuove aree (file ad- }
min/adminarea.php), nuovi ar- elseif ($righe==1) {
gomenti (file admin/admi- // accesso consentito e contemporanea registrazione della variabile di sessione di accesso e di una variabile di
narg.php) o nuovi giornalisti sessione che distingue un giornalista dall'altro
(file admin/admingiorn.php) $_SESSION['ok']=true;
contengono un form compilato $_SESSION['id_giorn']=$tab[0];
nel quale viene eseguita una }
query di tipo INSERT. Dalle listato 14: giorn/auth.inc.php
stesse pagine possiamo anche
modificare o cancellare aree,
argomenti e giornalisti: in que- Se da questa query non è $q="SELECT testo, date_format mente viene aggiornata la data
sto caso avremo di fronte un estratta alcuna riga (testo,'%d-%m-%Y') FROM testi_admin di ultima spedizione della new-
form vuoto e due pulsanti per (mysql_num_rows=0) allora WHERE id_testo='news'"; sletter inserendo la data odier-
modificare o cancellare i dati posso effettuare la cancella- $r=mysql_query($q); na (lezione 1):
del record già selezionato nella zione, altrimenti l'operazione $t=mysql_fetch_array($r);
pagina generale (l'identificati- non può essere effettuata. echo "L'ultima volta che hai spedito // aggiorno la data dell'ultima
vo del record è sempre tra- Nel caso dei giornalisti la la newsletter era il giorno spedizione con la data odierna
smesso e propagato con una cosa è aggirabile grazie al cam- <strong>".$t[1]."</strong><br/> $agg="UPDATE testi_admin SET
variabile POST). L'azione di po “attivo”: modificando il va- Dopo di allora sono stati pubblicati testo='".date('Y').date('m').date
modifica (il listato 13 si riferi- lore di questo campo e ponen- questi commenti:<p>"; ('d')."' WHERE id_testo='news'";
sce alla modifica di un argo- dolo a 'no' è possibile bloccare $sql="SELECT titolo, mysql_query($agg);
mento) si basa su una serie di l'attività del giornalista (non date_format(data_ins,'%d-%m-%Y')
if che controllano se i campi potrà più accedere all'area ri- FROM commento WHERE Adesso non ci resta che clic-
del form siano vuoti: se non lo servata e inserire articoli) sen- pubblicabile='si' AND care su logout (lezione 2) e
sono viene aggiunta l'istruzio- za cancellare i suoi dati dal da- data_ins>=".$t[0]." ORDER BY uscire dalla gestione dell'am-
ne specifica che finirà poi nella tabase. data_ins"; ministratore.
query UPDATE effettuata sul Ormai siamo esperti e modi-
record selezionato. ficare i testi o i nostri dati di L'amministratore deve solo, Area di gestione
La cancellazione, invece, im- amministratore (la nuova pas- se vuole, inserire un testo di ac- del giornalista
pone un controllo preliminare sword va inserita due volte per compagnamento alla newslet- Ogni giornalista presente nel
per conservare l'integrità del evitare errori di battitura) e gli ter e poi premere il tasto “Spe- database (in stato attivo) può
database: un giornalista, infat- iscritti alla mailing list non ci disci”: automaticamente la accedere ad un'area di gestione
ti, si può eliminare solo se non spaventa. newsletter verrà spedita agli specifica dalla quale potrà in-
ha mai scritto commenti e, allo Può essere interessante ve- iscritti (per rispetto della pri- serire e modificare commenti e
stesso modo, argomenti e aree dere come viene gestita la spe- vacy tutti gli indirizzi saranno foto, chiederne la cancellazio-
possono essere cancellati solo dizione della newsletter. L'ulti- in campo nascosto Bcc) e con- ne all'amministratore (non può
se non sono già legati ad un ar- ma data di spedizione è me- terrà l'indicazione dei nuovi farlo direttamente per scelta
ticolo. morizzata nella tabella commenti. Sempre automatica- dell'editore) e infine modificare
Per compiere la verifica si testi_admin, e questa data vie-
scrive una query come que- ne usata, al caricamento della 10
sta: pagina admin/adminnews. php,
per estrarre la lista degli arti-
$sql_c="SELECT id_commento FROM coli (immagine 10) che sono
commento WHERE stati pubblicati da quella data
id_argomento='".$_POST[id]."'"; in avanti:

$mod="";
if (trim($_POST[arg])!="") $mod.= "testo_argomento='".trim($_POST[arg])."', ";
if (trim($_POST[area])!="") $mod.= "id_area='".trim($_POST[area])."', ";
if ($mod!=="") {
$mod=rtrim($mod,", ");
// questo rtrim elimina la virgola e il carattere vuoto che si trovavano nella
parte destra di $mod
$modifica="UPDATE argomento SET".$mod." WHERE
id_argomento='".$_POST [id]."'";
mysql_query($modifica);
echo "<span class='titoletto'> Aggiornamento dell'argomento effettuato
</span><p>";
}
listato 13: admin/adminarg.php
Elenco dei commenti pubblicati dall'ultima spedizione della newsletter
5a lezione

11 rename ($dir1,$percorso.$

}
id_c."_1.jpg");
Gli altri corsi
Contestualmente all'inseri-
da Webmaster
mento del commento viene disponibili
mandata una mail all'ammini-
stratore (copia al giornalista) nel CD
per avvertirlo che c'è un nuovo
commento da approvare per la Nel CD Guida 2 allegato
pubblicazione sul sito. a questo numero di PC
Un giornalista può poi modi- Open, all’interno della
ficare (file “giorn/giornmod. cartella PDF/Corsi, trovate
php”) uno dei suoi articoli due corsi completi che
(comprese le immagini), però possono essere un utile
in questo caso il commento complemento al corso PHP.
modificato viene reso nuova- Uno è il corso Web
mente “non pubblicabile” e vie- Developer ASP, 97 pagine
ne mandata una mail all'ammi- suddivise in quattro lezioni
nistratore per informarlo che per capire come realizzare
deve ricontrollare il commento siti dinamici in tecnologia
modificato per approvarlo. ASP.
Le opzioni di gestione del giornalista Il giornalista non può can-
cellare i propri articoli, ma può
chiedere all'amministratore, at-
i propri dati di accesso. spettare tre condizioni decise traverso il form della pagina
La logica di accesso è uguale in fase di costruzione del sito: “giorn/giorncanc.php”, di far-
a quanto visto, ma diversa- larghezza e altezza dovranno lo: anche in questo caso all'am-
mente dal caso dell'ammini- essere minori di 120 pixel e ministratore arriverà una mail
stratore unico, l'autenticazio- l'immagine dovrà essere di tipo con la richiesta.
ne (il form di accesso si trova JPG. Con il logout usciamo anche
nel file giorn/index.php) dovrà Per controllare il rispetto di da questa area di amministra-
memorizzare l'identificativo queste regole uso la funzione zione
univoco del giornalista e verifi- PHP getimagesize, registrando Il sito dei commenti è adesso
care lo stato della sua registra- i valori ottenuti (larghezza, al- pronto per essere gestito e ag-
zione bloccando l'accesso ai tezza, tipo e attributi dell'im- giornato, e tutte queste opera-
giornalisti disattivati. magine) in una serie di variabi- zioni non saranno più compiu-
Usiamo allo scopo il file li grazie alla funzione list: te modificando il codice delle
giorn/auth.inc.php (listato 14) pagine. Il compito del WebDe-
introducendo un nuovo con- list($width1, $height1, $type1, $attr1) veloper è finito!
trollo sulla query di accesso e = getimagesize($_FILES
inizializzando una variabile di ['immag']['tmp_name'][0]); Conclusioni
sessione di nome “id_giorn” // l'immagine sarà caricata se Il corso WebDeveloper PHP Il corso Webmaster spiega,
che memorizza il valore della $width1<=120, $height1<=120 e (e MySQL) finisce qui, dopo 5 invece, in 88 pagine
chiave identificativa del gior- $type1=2 (il valore 2 indica un file jpg) lezioni, con questo esempio ap- suddivise in otto lezioni tutto
nalista. plicativo da studiare e riadat- quello che bisogna sapere
Questa nuova variabile ser- Passati questi controlli devo tare secondo le proprie esigen- per costruire un sito
ve ad impedire che un giornali- caricare l'immagine sul server ze. e imparare il linguaggio
sta possa vedere e modificare dandole come nome il codice Lo scopo del corso era far in- HTML 4.01, i CSS (fogli
gli articoli e i dati degli altri del commento cui si riferisce. tuire le potenzialità di un lin- di stile), Java Script e CGI.
giornalisti. Per ricavare il codice identifi- guaggio open-source server si- Il corso è completato da utili
Entriamo nella pagina gene- cativo (chiave) uso la funzione de come PHP, utilizzabile con consigli per promuovere
rale (immagine 11): inseriamo mysql_insert_id che mi resti- profitto sia in modalità stand il proprio sito on line.
come user il nome del giornali- tuisce proprio il codice che alone sia in coppia con un qual-
sta (es: “giuseppe”) e come cerco (estrae il valore del cam- siasi DBMS allo scopo di svi-
password il cognome (es: “ver- po autoincrementale presente luppare siti dinamici. E proprio
de”), entrambi minuscoli. Pro- nell'ultima query di inserimen- in un'ottica di completezza di
viamo poi a vedere cosa succe- to dell'articolo), quindi carico formazione del WebDeveloper,
de usando il giornalista giovan- l'immagine con move_uploa- sono stati approfonditi anche i
ni bianchi che è stato disabili- ded_file e infine rinomino (fun- concetti di base, teorici e pra-
tato. zione rename) l'immagine tici, della creazione di un data-
Riguardo le pagine di gestio- usando la codifica decisa in fa- base.
ne coinvolte, vale la pena spen- se progettuale: Gli esempi trattati sono stati
dere due parole sull'inserimen- presi da esperienze reali “sul
to delle immagini (lezione 3), $percorso="../img/"; campo”, ma, al solito, possono
operazione contestuale all'in- $dir1=$percorso.$_FILES['immag'] essere considerati solo un pun-
serimento del testo di un com- ['name'][0]; to di partenza per raggiungere
mento (file giorn/giornins. $id_c=mysql_insert_id(); nuovi traguardi... il limite, ge-
php). if($_FILES['immag']['name'][0]) { neralmente, è dato dalla nostra
Nel caso decidessi di inseri- move_uploaded_file($_FILES['immag'] fantasia.
re una o due immagini dovrò ri- ['tmp_name'][0], $dir1); Buon lavoro a tutti! 

You might also like