PHP e database: connessioni a MySQL In questo articolo mostreremo come sia possibile, all'interno di uno script PHP, collegarsi ad un database Mi/SQL per gestire in modo evoluto i dati dì una applicazione.
Luca Balzerani <l.balzerani@lmuxpratico.com>
La maggior parte delle applicazioni non banali (che non rientrano, quindi, nel novero gli innumerevoli Hello, world! attraverso cui tutti siamo passati) necessita di una gestione dei dati.
connessa e per cui parliamo di connessione piutto
Se, nei casi più semplici, questa può essere basata sul
sto che, ad esempio, di accesso.
l'uso di normali file, in quelli in cui emergono esigenze
L'interazione tra l'applicazione che accede ai dati
più sofisticate è praticamente inevitabile avere a
{uno script PHP, nel nostro caso) ed il server MySQL
che fare con dei database e, conseguentemente,
è analoga allo svolgimento di una normale conver
con i software che li gestiscono, cioè i DBMS (Data
sazione telefonica, risultando articolata in tre fasi
Base Management Systems). La funzione dei DBMS
principali.
è quella di nascondere al programmatore la com plessità intrinseca nella gestione dei dati: immagaz
La prima fase è quella di connessione: il
zinare grandi quantità di dati ed eseguire su di essi
chiamante compone il numero telefonico della
interrogazioni ed aggiornamenti, infatti, sono opera
persona con cui vuole parlare e la rete telefonica
zioni che coinvolgono strutture dati ed algoritmi
provvede ad instaurare la connessione, creando
complessi.
un canale di comunicazione tra i due
Grazie ai DBMS il programmatore non deve preoccu
interlocutori;
parsi di tali dettagli e può operare sui dati attraverso
La seconda fase consiste nella conversazione tra
una opportuna interfaccia di programmazione (API,
chiamante e chiamato e corrisponde
Application Programming Interface), caratterizzata
all'interazione in senso stretto tra di essi;
da un maggiore livello di astrazione, fornita dal
L'ultima fase, attuata al termine della
DBMS stesso. MySQL, a cui faremo riferimento in
conversazione, è l'abbattimento della
questo articolo, è un esempio di DBMS.
connessione, effettuato nel nostro parallelo con il
Ne esistono naturalmente anche altri, ognuno con
riaggancio dell'apparecchio telefonico.
le proprie peculiarità, ì propri punti di forza e le pro prie limitazioni.
La descrizione appena fornita si applica alla perfe
Nel nostro caso abbiamo optato per MySQL per una
zione al compito che ci siamo prefissi, una volta
serie di ragioni: in primo luogo MySQL è uno dei
stabilite le seguenti corrispondenze:
DBMS più diffusi in ambito Linux, poi è OpenSource ed infine, particolare non trascurabile, è disponibile
il chiamante, nel nostro caso, è l'applicazione
anche per piattaforme Windows, per cui è possibile
in PHP;
utilizzarlo praticamente in ogni contesto.
Modalità di connessione
il numero telefonico corrisponde ai parametri di connessione (di cui parleremo tra breve); il chiamato non è altri che il server MySQL;
Qualche lettore si sarà certamente chiesto come
la conversazione consiste nell'invio, da parte
mai stiamo utilizzando il termine "connessione" per
dell'applicazione PHP, di comandi SQL, a cui fa
indicare l'accesso ad un database. La spiegazione è
seguito una opportuna replica (costituita
semplice: MySQL (ma lo stesso vale per molti altri
tipicamente da dati] da parte di MySQL.
DBMS) è un'applicazione autonoma, indipendente dai programmi che accederanno ai dati.
Parametri per la
Esso viene eseguito sotto forma di "demone": si
connessione
tratta di un programma (mysqid) che, una volta lan ciato, si pone "in ascolto", in attesa cioè di essere
Per poter stabilire una connessione con MySQL
contattato da altre applicazioni che ne richiederanno i
abbiamo bisogno di conoscere alcuni importanti
servizi. Quindi, per poter operare su un database
parametri. E' necessario, innanzitutto, sapere dove
MySQL, un'applicazione deve effettivamente "chia
si trova, sulla rete, MySQL: esso può essere in ese
mare" il demone mysqtd, instaurando una connes
cuzione sulla stessa macchina su cui stiamo lavo
sione che permetterà la comunicazione tra i due
rando (il caso più probabile) oppure può essere
programmi. Si comprende, quindi, la ragione per cui
situato su un altro computer della rete; nel primo
questa modalità di comunicazione viene definita
caso il valore da utilizzare sarà localhost, nel
secondo sarà il nome (o I'IP) delia macchina che
creato automaticamente un utente di nome root
ospita MySQL Nel nostro caso supponiamo di lavo
(come il super-utente di Linux, ma ripetiamo che
rare su un unico PC per cui useremo localhost.
non si tratta della stessa cosa) con password vuota.
Il secondo parametro riguarda il nome del database
Se tale configurazione non è stata modificata, le
su cui operare; MySQL. infatti, consente di creare
suddette credenziali ci permetteranno di accedere a
più database, tra loro indipendenti. Per non compli
MySQL (se. invece, sono state apportate delle modi
care inutilmente la trattazione, useremo un database
fiche, le nuove credenziali dovrebbero essere note).
di nome test (inizialmente vuoto) che viene creato
Riepiloghiamo quanto detto sui parametri di con
automaticamente in ogni installazione di MySQL ed
nessione mostrando il primo frammento di codice
è adibito ad "area di prova".
PHP. nel quale i rispettivi valori sono memorizzati in
Gli ultimi due parametri sono il nome utente e la
altrettante variabili.
password per l'accesso. A questo proposito è bene chiarire subito che MySQL ha una propria gestione
<?php
degli utenti, totalmente indipendente da quella
//
usata da Linux.
Snomehost
-
"localhost";
parametri
per
la
connessione a
In altre parole, se sulla vostra macchina Linux avete
Snomedb
■
"test";
creato un utente di nome luca, questo non implica
Snomeutente
=
"root";
che esista anche un utente MySQL con lo stesso
Spassword
=
"";
MySGL
nome (e normalmente, infatti, non è così). Ancora una volta, per non aggiungere troppa carne
al fuoco, ci limiteremo ad utilizzare dei parametri
A questo punto siamo pronti per entrare nel vivo
predefiniti: quando viene installato MySQL viene
del procedimento.
INFORMAZIONI
Le funzioni utilizzate
dati. Il valore restituito dalla funzione è FALSE in caso dì falli mento dell'esecuzione (a causa, ad esempio, di un errore sin
Di seguito presentiamo un riepilogo delle funzioni della libreria
tattico nel comando SQL), altrimenti è un intero che identifica
MySQL utilizzate nell'articolo. Per ogni funzione riportiamo una
il risultato prodotto dalla query e deve quindi essere memoriz
breve descrizione e la spiegazione dei parametri in input e del
zato in una variabile per potervi accedere.
risultato restituito. Squery: il comando SQL da eseguire Sconnessione: l'identificativo della connessione
Mysqi Connect
MySQL; è il valore restituito da mysql connectt )
mysql connectisnomehost,
Snomeutente,
Spassword)
Stabilisce la connessione con il server MySQL in base ai para metri forniti. Restituisce il valore FALSE se il collegamento non
va a buon fine; in caso contrario il valore restituito (un numero
Mysql_letch_row mysql
fetch
rowlsrisultato)
intero) funge da identificativo della connessione, per cui è
Restituisce il record successivo della query eseguita, se dispo
necessario memorizzarlo in una variabile per i successivi usi.
nibile, oppure il valore FALSE se non vi sono altri record da restituire. Nel primo caso il record e formio sotto forma di un
Snomehost: il nome della macchina su cui è in
array i cui elementi sono i campi della query.
esecuzione il server MySQL; se si lavora sul proprio computer è sufficiente specificare localhost
Srisultato: l'identificativo del risultato prodotto da
Snomeutente: il nome dell'utente MySQL con cui
un'invocazione della funzione mysql query( )
autenticarsi
Spassword: la password associata all'utente MySQL
Mysql_feteh_array mysql
My5ql_snlect db
fetch array(Snsultato)
Analoga a mysql mysqlselect
db(Snomedl),
Sconnessione)
fetch
row{ ), se ne differenzia solo in quan
to restituisce il record corrente sotto forma di array associati-
Seleziona la base di dati su cui operare (MySQL, infatti, con
vo, per cui è possibile accedere ai campi sia per nome che per
sente di gestire più di un database). Restituisce un valore logi
posizione.
co: TRUE se il database è stato selezionato correttamente. FALSE in caso contrario (ad esempio se si è tentato dì selezio
nare un database inesistente).
Mysql_cloBB mysql close(Sconnessione)
Snomedb: il nome del database su cui operare
Sconnessione: l'identificativo della connessione a MySQL; è il valore restituito dalla precedente chiamata a mysql connect{)
Sconnessione: l'identificativo della connessione MySQL; è il valore restituito da mysql connect( )
Mysql query mysql querytSquery,
Chiude la connessione con MySQL.
La documentazione di PHP è molto ampia e ben fatta, per Sconnessione)
maggiori informazioni sulle funzioni, sul loro funzionamento interno, per esempi e trucchi di utilizzo si consiglia la consul
Esegue un comando SQL ("query"). E' la funzione attraverso
tazione dei manuale ufficiale su:
la quale si esplica l'interazione vera e propria con la base di
http : /Aw«/. php. net/marmai /
LISTATO 1
Le funzioni PHP
Collegamento aS
per MySQL
database MySQL
Si è detto in precedenza che ogni DBMS mette a disposizione del programmatore una API che consente dì utilizzarne le funzionalità. MySQL non fa eccezione:
//
in PHP abbiamo a disposizione una serie di funzioni,
Snomehost
=
contraddistinte dal prefisso mysql , che costituisco
Snomedb
= "test";
Snomeutente
= "root";
Spassword
= "";
no, nel complesso, la "libreria MySQL'.
Le funzioni disponibili sono numerose e non sarà possibile presentarle tutte in questa sede: rinviamo
quindi il lettore interessato ad approfondire ulterior
parametri
per la connessione a MySQL "localhost";
Sconnessione = mysqlconnectlSnomehost, $noitteutente,
mente l'argomento alla documentazione ufficiale del linguaggio PHP. In questo articolo utilizzeremo, nell'ordine, le seguenti funzioni (riepilogate e docu mentate nell'apposito riquadro):
if
((Sconnessione)
Spassword);
t
diefConnessione non
riuscita:
".mysql errori));
} else { echo "Connessione riuscita!<br>";
> mysql connectO per aprire la connessione con
I
MySQL;
> mysql. select db( ) per selezionare la base di
if
dati su cui operare; > mysql query() per eseguire comandi in fetch
{
selezionato con
successo!-=br>";
} else{
linguaggio SQL ("query"}; > mysql
(mysqlselect db(Snorredb)) echo "Database
dieCTmpossiblle
selezionare
il
database;" .mysql errori))
row( ), e relative varianti, per
accedere ai risultati delle query; mysql
closeO per chiudere la connessione al II
termine della sessione di lavoro.
esecuzione comando
Ssql
viene salvato in una variabile (Sconnessione).
connect(Snomehost,
NOT MJLL.
Srisultato = mysql_query(Ssql,
if
(SnsuUato) echo
Sconnessione = mysql
(
PRIMARY KEY(codice))'1;
parametri di connessione: il nome dell'host su cui è in esecuzione MySQL, il nome utente e la sua relati
SQL
TABLE prodotti
descrizione VARCHAR(60)
connect(); a cui vengono forniti tre dei
va password. Il risultato restituito dalla funzione
"CREATE
codice INT,
La prima istruzione è l'invocazione della funzione mysql
=
"Comando
Sconnessione);
{ eseguito
con
successo!«:br>";
} else {
Snoneutente.
Spasswordl;
echo "Comando
non
riuscito..,<br>";
II valore assegnato a Sconnessione ci permette di scoprire se il tentativo di collegamento a MySQL è
mysql_ dose (Sconnessione);
andato a buon fine. Se tale valore è FALSE vuoi dire
7>
che qualcosa è andato storto; in questo caso sugge riamo di ricontrollare i passi eseguiti fìn'ora. Se, al contrario, il valore è diverso da zero, allora la connessione è stata stabilita e possiamo procedere.
Se fino a questo punto tutto è andato secondo i
Il test sull'esito della connessione sarà simile al
piani, siamo pronti per operare sul database.
seguente:
Questo vuoi dire che è arrivato il momento di fare conoscenza con il linguaggio standard per la manipola
ìf
( ! Sconnessione)
zione di database: SQL. Prima di procedere, tuttavia,
{
dieC'Connessione non
}
else
{
echo
"Connessione
riuscita:
".mysql
errorO);
mostriamo come chiudere la connessione al termi ne della sessione di lavoro con il database. Così
riuscital^br»";
come la procedura di connessione appena vista
sarà il prologo comune a tutti gli script che accede ranno al database, analogamente la disconnessione Eseguita la connessione, il passo successivo è la
selezione del database. L'istruzione corrispondente
ne sarà il comune epilogo. L'istruzione di disconnes sione è la seguente:
è molto semplice: mysq\_ dose (Sconnessione); if
(mysql_select db(Snomedb))
{
echo "Database selezionato con sjccesso!<br>"; ) else{
dieC'lmpossibHe selezionare il database: ".mysql errori)1 ;
Esecuzione dei comandi SQL Ora che sappiamo come collegarci a MySQL ed abbiamo predisposto dei comandi da eseguire sul
database, non ci resta altro da fare che eseguirli, procedimento da utilizzare sarà sempre io stesso: Ssql
=
"...";
//
il
comando
da
Srisultato = mysqlquerylSSQl,
if
ISnsultato)
eseguire
(Srisultato) while
{
(Srecord = mysql fetch_row(Srisultato])
echo
"Codice:
"
.
echo
"Descrizione:
Srecord|Q] "
.
.
"
■
Srecord[1]
{
"; .
"<br>";
Sconnessione);
{
echo "Comando eseguito
con successo!<br>";
Come si vede, nel caso che l'esecuzione del coman do SQL abbia avuto esito positivo invochiamo ripe-
} else { echo
if
"Comando
non
riuscito...<br>";
tutamente la funzione mysql fetch row(), ferman doci solo nel momento in cui essa restituisce il valore FALSE. Fino a quando ci sono record da acce
Assegnando alla variabile ssql il primo comando,
dere, invece, essa restituisce un array con tanti ele
otteniamo complessivamente lo script mostrato nel
menti quanti sono i campi ottenuti dalla query.
listato 1. La predisposizione di uno script per l'ese
Ad ogni invocazione di mysql fetch
cuzione del secondo comando non presenta difficoltà,
automaticamente "consumato" un record, passando
row() viene
in quanto sarà sufficiente assegnare a $sql il secon
al successivo.
do frammento SQL.
Mei nostro caso abbiamo selezionato (con l'asteri
Le cose cambiano, invece, per l'esecuzione del terzo
sco *) tutti i campi della tabella prodotti, quindi
comando, cioè dell'interrogazione del database. In
avremo due colonne, rispettivamente codice e
questo caso, infatti, non ci limitiamo ad eseguire un
descrizione. Per intenderci, nell'esempio mostrato
comando ed a verificarne l'esito: se l'interrogazione
l'array
è stata eseguita con successo siamo anche interes
mysql_fetch row{ ) sarà identico a quello prodotto
sati a visualizzarne i risultati.
dalla seguente istruzione:
restituito
dalla
prima
chiamata
a
E' a questo punto che entrano in gioco la funzione mysql
fetch_ row( ) e le sue varianti. Vediamo subi
Srecord
= arrayd,
"Computer
(nodello XYZ");
to cosa dobbiamo aggiungere al nostro prototipo di script.
Di conseguenza il primo elemento dell'array, che contiene il valore del campo codice, è accessibile come 5record[0]; il secondo, corrispondente alla
INFORMAZIONI
Un pò3 di SQL
descrizione, come $record[l] e così via. L'accesso, in altre parole, è posizionale.
Questa modalità di referenziazione dei campi può creare, però, dei problemi. Cosa succede nel
SQL è una sorta dì "lingua franca" per la gestione dei data
momento in cui modifichiamo la nostra query o le
base relazionali, un linguaggio ampiamente standardizzato
tabelle che essa interroga? Fin quando ci limitiamo
che consente di operare pressoché su ogni DBMS.
ad aggiungere nuovi campi a destra non ci sono dif
Ovviamente una trattazione di SQL è al di fuori degli scopi di questo articolo, per cui ci limiteremo a mostrare alcuni
esempi di comandi. Il primo comando che andiamo ad esa
ficoltà; se, ad esempio, volessimo aggiungere alla tabella prodotti il campo prezzo, la nostra query
minare serve a creare una tabella, denominata prodotti,
produrrebbe
contenente due colonne (o campi), codice e descrizione.
$record[2] troveremmo il prezzo del prodotto cor
tre
colonne
anziché
due
e
in
Il codice costuisce la chiave primaria nel senso che identifi
rente. Ipotizziamo, però, che le modifiche apportate
ca univocamente ogni singola riga (record) della tabella. Il
alla query comportino un cambiamento dell'ordine
comando è il seguente.
delle colonne: è evidente che ci troviamo costretti a modificare tutto il codice di accesso ai record in
CREATE TABLE
prodotti
(
quanto ì vari campi non si trovano più nella posizio
codice INT, descrizione
VARCHAR(6G)
HOT fJULL,
PRIMARY KEYIcodice)
ne originaria. Se a tutto ciò aggiungiamo una ulte riore considerazione, meno cruciale ma non per
questo trascurabile, e cioè l'innegabile scomodità di referenziare i campi in base alla loro posizione, ci
II secondo comando inserisce un record nella tabella appena creata, specificando i valori da assegnare ai diversi campi.
convinciamo definitivamente dell'opportunità di adottare una modalità migliore. Questo diverso
modo d'accesso ai campi di una query sarà tra gli INSERT INTO prodotti!codice,descrizione) VAIUES(1,
'Computer modello xrZ')
II terzo ed ultimo esempio di comando SQL è una query "in senso stretto", cioè definisce un'interrogazione del databa se. Nel caso specifico con il seguente frammento SQL chie diamo al DBMS di restituirci tutti i record della tabella pro dotti, ordinati alfabeticamente per descrizione. SELECT •
FROM prodotti ORDER BY descrizione
argomenti delle pagine che seguiranno.
Conclusioni Lo studio dei database e delle relative modalità di utilizzo è propedeutico a qualunque progetto software, indipendentemente dal linguaggio di programma zione o dal dominio applicativo.
L'utilizzo dei DB in unione a PHP. come si è potuto osservare, è estremamente semplice e pratico, pur ché si abbiano conoscenze minime di SQL.
Come gestire una community in PHP! Vi siete nini chiesti come si realizzano le zone ad accesso riservato nei siti web? La risposta è molto più semplice di quanto pensiate... basta un po' di PHP e tanta buona volontà!
Luca Gambetta <\.gambetta@linuxpratico.con!>
empre più spesso sorge la necessità di realiz. zare siti web che permettano ad una comuni tà di utenti di interagire o renderli unici fruito ri di contenuti speciali.
testo che non
dovrebbe esserci<?php
Capita ancora più spesso che malintenzionati decida no di "fare danni", andando a toccare dati che non
session starti);
gli competono e portando scompiglio... Per far fronte a
queste necessità non c'è niente di meglio che un
7>
sistema di autenticazione in Php.
<html>...
Sostanzialmente un utente del sistema può essere ...vi comunicherà un bel messaggio di errore, infor
visto come un insieme delle seguenti informazioni: ìdentificativo numerico (il cosidetto UID, User ID),
mandovi dell'impossibilità di aprire la sessione.
nome (che corrisponde alla login) e parola chiave per
Tornando al nostro sorgente, esso, dopo aver inizia-
l'accesso al sistema (la cara vecchia password).
lizzato la sessione, verifica se la pagina sia stata
Implementeremo il nostro sistema di gestione degli
invocata usando il metodo HTTP P05T e altresì esista
accessi utilizzando ìe variabili di sessione, che sono
tra le variabili quella chiamata frm testo, che con
una interessante caratteristica di Php. In questo arti
tiene il testo immesso nel campo di input:
colo getteremo le basi per un più sofisticato sistema che termineremo nelle prossime pagine.
if
<$ SERVER!'REQUEST METHOD'l
==
'POST'
£&
array keyexìstsl'frm testo',
il potere delle sessioni...
S POST))
{
In sostanza, che cosa sono le sessioni e cosa possia
Come potete vedere ho usato l'array superglobale
mo farci? L'interprete Php, grazie alle sessioni, per
S
mette di superare un grosso scoglio (chiamarlo
frm testo nell'altro array superglobale s
"difetto" è sbagliato) del protocollo HTTP, ossia l'es
In seguito viene creata la variabile di sessione testo,
sere "stateless", privo di stato. Ciò vuoi dire che il
a cui viene assegnato il valore della variabile
nostro server HTTP (di solito Apache) "dimentica"
S POSTI'frm
SERVER e successivamente verificato se esista POST.
testo']:
tutte le richieste che gli abbiamo inoltrato, come pure le variabili che abbiamo passato ad una pagina.
if
Per evitare questo inconveniente sono stati creati i
(get magie quotes gpcO)
S SESSIONE'testo']
famosi cookie, che altro non sono che piccole strin
}
ghe di testo che il server ci invia.
else
{
=
strip5lashes(S POST['fnn
=
S_POST[ 'frm
testo']);
<
S SESSIONCtesto']
testo1 ];
Cosa c'entrano i cookie con le sessioni? Una sessione
viene referenziata dall'interprete Php da un identifi catore alfanumerico, il cosidetto ID di sessione, gra
INFORMAZIONI
zie al quale viene creato un file su! server. Questo ID
di sessione viene mandato al client grazie ai cookie o, se questi sono disabilitati, si cerca di prelevarlo
Gestire i dati che
dalle variabili arrivate allo script dall'URL. Come
vengono dall'esterno
esempio di utilizzo ho scritto gii script sessioni.php e usasessione.php.
Passiamo subito a vedere nella pratica come fare: ci
Nel nostro esempio notate un particolare interessante: prima di
assegnare il valore della variabile ho verzicato se fosse attiva
rifaremo allo script sessioni.php, che vi permette di
una caratteristica di Php mediante l'utilizzo della funzione
inserire un testo e ritrovarlo alla pressione del pul
getmagic quotes gpc( ). L'interprete infatti si preoccupa (per
sante "Invia!". La funzione Php che inizializza (e nel
caso fosse necessario crea ex novo) una sessione è session
start(), che va invocata prima che qual-
siasi output sia stato inviato al browser. Con ciò voglio dire che l'interprete Php, se si troverà di fronte qualcosa tipo...
evitare la cosiddetta "5ql injection") di anteporre un carattere \ (backslash). davanti ad alcuni caratteri "speciali", tra cui l'apo strofo, in tutte le variabili POST, GET e nei COOKIE, se la variabi le di configurazione magie quotes gpc è pari a 1. Prima di
creare la variabile di sessione elimineremo perciò gli eventuali backslash con una chiamata alla funzione 5tripslashesO. .._
~ Quando una sessione è ìnizializzata correttamente
cookie: se questi non sono disponibili {ad esempio se
avremo a disposizione un array superglobale chia
disattivati nel browser) verrà ricercata una coppia di
mato ì SESSION, in cui verranno conservate tutte le
valori possibili, come detto, tra le variabili inviate
variabili, che verranno appunto definite "di sessione",
tramite richiesta GETo POST.
che sono state definite. Ovviamente potremo crear
Il problema della propagazione dell'identificativo di
ne di nuove, per far ciò basta un semplice:
sessione è uno degli scogli principali quando si utiliz zano le sessioni: come soluzione sicura conviene
S SESSIONEi'nome'J
a
sempre propagare "a mano" questo valore, in modo
valore;
da essere sicuri che arriverà alta pagina successiva. Non c'è nessun vincolo al tipo di dato che potete sal
E' proprio quello che facciamo nel sorgente di
vare nelle sessioni: sia esso un intero, un array, o
sessione. php con le righe:
quant'altro supportato da Php. Come vedete $ SESSION si comporta esattamente
<input
type="hidden" name="<?=
come un array. tenetelo a mente, dato che potrete
sessinnnamel);
value="<?=
?>"
session
id();
?>">
utilizzare su di esso tutte le funzioni che in questo frangente Php ci mette a disposizione.
E successivamente:
Ovviamente oltre che creare variabili di sessione, possiamo anche decidere di distruggerle. Per far ciò
<a
dref="usa sessione.php?<?=
basta usare la funzione unsetl ) in questo modo:
session name(),'■'.session idi);
?>">Verifica quanio immesso..,</a>
unset(S SESSIONI'nomevariabile']! ;
Se adesso cliccate sul link "Verifica quanto immes Per distruggere del tutto una sessione ed i dati in
so..." e leggete nell'URL vi troverete gli stessi valori
essa conservati invece bisogna utilizzare le seguenti
presenti nel sorgente di sessione.php. Ancora più
istruzioni:
eloquente è utilizzare l'ID di sessione per verificare
*~
direttamente come vengano conservati "fisicamensession unsett);
te" i dati. In figura 1 ho come ultima parte dell'URL
session destroyi);
la stringa:
La prima distrugge tutte le variabili conservate nella
?PHPSESSIO=5cleb1eel7ea2b6c5f6G297f80135dGa
sessione, mantenendo però il codice identificativo delia stessa. La seconda fa piazza pulita di tutto:
Sappiamo perciò che la nostra sessione ha come
dopo la sua invocazione sarà necessario ricreare
nome
una sessione ex novo utilizzando la funzione
'5c4eb4eel7ea2b6c5f60297f80135d0a'. Ho aperto un
session
terminale come utente root e ho dato il comando:
starti).
'PHPSES5ID'
e
come
valore
di
ID
A questo punto penso vi sia sorto il dubbio su come
faccia l'interprete Php a capire con quale sessione
fl
cat
/tmp/sess 5c4ebfleel7ea2b6c5f60297fB0135dSa
abbia a che fare tra le tante possibili. Ogni volta che invochiamo la funzione session_start( ) viene veri-
E... magia... ho stampato if contenuto della sessione!
ficato se esista tra i cookie, le variabili dì tipo GET e
Avevo detto che le sessioni vengono
quelle di tipo POSI, un identificatore col nome pari a
servate in un file sul server: adesso sappiamo anche
quello restituito dalla funzione session namet ).
in che modo.
Questo identificatore ha poi un valore che deve corri
Come nota a margine c'è da dire che questa è solo
spondere
una veloce introduzione: vi consiglio di approfondire
a
quello
restituito
dalla
funzione
session id< ). Il passaggio dell'identificativo di ses
di norma con
nel manuale di Php e di provare quanto più possibile.
sione tra una pagina e l'altra avviene attraverso i Un gestore di utenti fatto bene prevederebbe tre passi distinti prima di giungere al fatidico "ingresso" dell'utente. Di solito questi passi sono, nell'ordine, identificazione, autenticazione ed autorizzazione.
Perché suddividere una operazione semplice (del resto a noi basterebbe solo verificare se login e
1 ■■■■1
I
password corrispondano a quelle che conserviamo)
in così tanti passi?
SJSBMSiSM
ruot B echo 'cat ^tnp/scss^5c1ebìecl7ea2b6cSf&0Z'J7fn0l35d0n' testols:Zl:"lesto nella sessione!":
root b |
Il motivo è tutto da ricercarsi nella qualità e successi va solidità del sistema che stiamo mettendo su. Per capire meglio quanto sto dicendo analizziamo insie me i tre passi.
Con l'identificazione verifichiamo se un utente esista effettivamente nel sistema (pinco è tra gli utenti del Ecco spiegato l'arcano: nel terminale potete
vedere come vengano salvate le sessioni
nostro portale?}. Se ciò accade passiamo all'autenti cazione dello stesso; che consiste nel verificare se un utente che esiste nel sistema abbia un qualcosa
~
che gli permetta di dimostrare la sua identità.
cambiare il modo in cui conserviamo le informazioni
Questo "qualcosa" può andare
degli utenti, per quanto riguarda gli script di autenti
dalla classica parola
chiave, ad una Smart Card con codice segreto.
cazione cambieremo davvero poco codice.
Come ultimo passo c'è quello dell'autorizzazione:
Ritorniamo al sorgente: eseguiamo subito un control
avendo verificato le credenziali dell'utente che vuole
lo per verificare se lo script sia stato invocato con
entrare, registriamo (sia nella sessione che magari in
una richiesta HTTP POST e se esistono le variabili
un archivio) quanti più dati possibile riguardo il suo
frm
conto che possano esserci utili in futuro.
verifica vuoi dire che lo script è stato correttamente
login e frm_passwd: se questa condizione si
Come vedete impostando così le cose possiamo
invocato dal nostro form di togin e qualche malinten
creare sistemi completi di gestione degli accessi, in
zionato non sta cercando di fare il furbo.
maniera quasi del tutto sicura.
A questo punto ripuliamo i dati in ingresso e lì met
A questo punto è tempo di tuffarci nel codice sorgen
tiamo nelle variabili slogin e spassword. La ripulitu
te, per vedere dal vivo come impostare !e cose. Nella
ra è necessaria, come visto, per il problema degli
sottodirectory autenticazione/ troverete una serie
eventuali backslash aggiunti automaticamente dal-
di sorgenti, che saranno la base per ii nostro sistema
i'interprete Php.
di autenticazione. Esso funziona così:
Entra in gioco la funzione Identificai ):
All'utente viene mostrato il modulo per il login,
Sdati utente =
contenuto nel file index.php. Questo modulo,
ìf
IdentificalSLogin);
(Sdati utente
!==
false]
{
una volta premuto su "Entra1", conserverà nelle variabili POST frm login e frmpasswd i dati immes
Essa ritorna FALSE se qualcosa va storto o dei dati
si. Una form di login (o che contenga dati sensibili)
(dei quali ancora non sappiamo nulla) che dovranno
va sempre - e, ripeto, sempre - inviata col metodo
essere poi passati alla funzione di autenticazione. La
POST. Sarebbe poi ottimale se il tutto avvenisse
funzione Identificai) si preoccupa di estrarre da
anche in maniera crittata (ossia usando il protocollo
un database una serie dì informazioni relative ad un
HTTPS). ma spesso ciò non è possibile.
utente: poiché vogliamo che queste informazioni siano il più generiche e riutilizzabili possibile, lascia
Inviati i dati il controllo passa al file login. php,
mo che siano le funzioni stesse a manipolarle.
£- /che si preoccupa di prelevare le variabili dalla
Vedremo nel prossimo paragrafo come ciò avvenga:
richiesta HTTP di tipo POST, ed eseguire con esse i
per adesso ci interessa fecalizzarci sul processo di
tre passi di identificazione, autenticazione e autoriz
autenticazione. Supponiamo che il processo di identificazione sia
zazione.
andato a buon file: adesso il controllo passa alla fun •^
1
Se anche uno solo dei passi fallisce, all'utente
zione Autenticai ). che accetta la password ed i dati
viene presentato un messaggio di errore.
ritornati da Identificai ).
Altrimenti viene creata una sessione e registrata all'interno di essa un array, dal nome utente, che
if
(Autentica(SpassworO,
Sdatiutente))
{
contiene tutte le informazioni che possono esser utili
per indentificare l'utente corrente. Tra queste è inte
Questa funzione verìfica se la password registrata
ressante notare la presenza dell'indirizzo IP dell'u
nel database degli utenti corrisponde a quella che ci
tente stesso e del codice della sessione, per evitare
arriva dalla form. Se anche questo scoglio viene
possìbili "trucchetti" da parte di malintenzionati.
superato, resta solo da autorizzare l'utente, cosa che
Successivamente l'utente viene dirottato ad una
avviene con la funzione Autorizzai ), a cui vengono
pagina riservata, che nel nostro caso è segreto.php.
passati, al solito, i dati utente.
All'utente viene data la possibilità di uscire dal-
/ l'area riservata, attraverso dei link allo script
Sutente -
if
Autorizza(Sdatiutente);
(Sutente
!== false)
{
logout.php, che si preoccupa di distruggere i dati sensibili dalla sessione.
Se finalmente è tutto a posto, Autorizzai) ritorna un array contenente varie informazioni utili, a cui
Il file login.php è cruciale e molto semplice nella
aggiungiamo i dati relativi all'indirizzo IP dell'uten
sua struttura. Esso si apre con l'inclusione di tre file:
te e l'ID della sessione che abbiamo prontamente
il primo, config. ine.php, contiene la configurazione
inizializzato:
de! sito, che viene posta nell'array Ssiteconfig; il secondo, auth.inc.php, raggruppa tutte le routine
session
per la gestione dell'accesso al sistema; infine lo
Sutentefip']
script auth
Sutentet'sid']
utils . ine ,php contiene diverse routine
usate per il login, comuni per ogni motore di autenti
starti);
= S SERVER!'REMOTE ADOR'l: =
session id();
S SESSIONI'utente')
= Sutente;
cazione che utilizzeremo. Il perché di questa scelta è presto detto: estrapolan
Come vedete come ultimo passo salviamo tutto
do le routine e rendendole il più generiche possibile,
l'array putente (frutto di tutte le elaborazioni) nella
possiamo realizzare una soluzione facilmente manu-
sessione, col nome (fantasioso...) di utente. La fun
tenibile, riutilizzabile e, soprattutto, estensibile. Ciò
zione Autorizzai) dovrebbe preoccuparsi anche di
vuoi dire che se un domani (come vedremo) volessimo
registrare la data dell'ultimo accesso dell'utente,
INFORMAZIONI
a Che cosa sana i file
3 passi e vìa! Per comprendere appieno il processo di gestione del
passwd?
l'accesso degli utenti, in questa prima puntata pre senteremo delle routine che si appoggiano a file di
II file /etc/passwd contiene varie informazioni sugli utenti di
un sistema Unix. La sua struttura, come potrete sincerarvi con sultando il manuale con man 5
passwd, è davvero banale,
tanto da rivelarsi adattissima a manipolazioni e veloci implementazioni. ma ha come svantaggio di diventare scomoda da
testo in formato passwd (riferitevi all'apposito riqua dro per un approfondimento). E' ovvio che in un ambiente reale non utilizzeremo mai tale approccio, in quando troppo limitante. Prendetelo come un
gestire al crescere del numero di utenti.
importante allenamento in vista della prossima pun
Il file /etc/passwd è composto da tante righe di testo, ognuna
tata, in cui si farà sul serio utilizzando motori per
per ogni utente del sistema. Le varie righe sono poi organizza
Database.
te in tanti campi separati dal carattere di due punti ";". secon do questo ordine:
Passiamo
subito
all'analisi
della
funzione
Identificai), che è la prima ad essere invocata.
utente:password;uid;gid:dati personali:directory homeisheU
Innanzitutto viene inclusa la variabile globale
Ho implementato lo script bash genera passwd. sh per creare
file contenente gli utenti. Dopo aver controllato se la
Ssiteconfig, dalla quale prenderemo il nome del file in stile passwd. che contengano i seguenti campi: utente : hasti
rad 5
della
stringa di login sia valida, leggiamo tutto il file delle
password, in un colpo solo, usando la funzione
password
file( ), che pone le singole righe di testo in un array Manipolare una stringa del genere è molto semplice usando le
o ritorna il valore FALSE se qualcosa è andato storto.
funzioni explode( ) ed implode{ ). Ad esempio possiamo in un
Notate come io abbia preposto il carattere @ all'in
colpo solo ottenere le singole voci, con:
vocazione della funzione, per far sì che l'interprete
Sdati =
Php non emetta a video eventuali messaggi di errore.
"utente:47283473fd:1234S667";
listiSlogin,
Spassword,
Slastlogin)
~
=
explodel':',
Sdati);
Sdb = @filetssite_config['donarne'J);
II costrutto listo associa i valori di un array alle variabili.
lf
[Sdb
!==
false!
{
A questo punto mi resta solo da cercare nelle singole
SORGENTE
codice sorgente? Potete trovare il codice sorgente descritto in questo articolo al seguente indirizzo: http://vjww.Unuxpratico.com/sviluppo/php/piip sessioni, tgz
voci quella corrispondente, e ritornare l'intera riga di testo:
foreach(Sdl)
as
listi Sutente, if
Sriga)
{
Spassword)
(istrcmpISutente,
= esplode(':',
Slogin))
return
Sriga);
trim(Sriga);
Per visualizzarlo dovrete estrarlo in una directory raggiungi
bile da Apache (peresempio /var/www/html/): /var/www/html # tar zxvf
/percorso/di/php sessioni.tgz
e collegandovi con il browser all'indirizzo del Web Server in esecuzione sulla macchina (IP o localhost).
Se osservate il sorgente della funzione Autenticai ), vedrete che questa semplicemente controlla se l'hash MD5 della password registrata nella stringa che ha generato Identificai) corrisponda a quello
passatogli. informazione che è sempre utile: in questa prima
"
>er concludere
implementazione ciò non avviene, ma lo faremo
Adesso abbiamo gli attrezzi minimi per gestire gli
nella prossima puntata.
utenti, ci manca solo una funzione per verificare se
L'ultimo passo da fare a questo punto è quello di
l'utente sia chi sostiene di essere ed invocarla all'ini
portare l'utente in una pagina (che può essere riser
zio di tutte le pagine che vogliamo proteggere. Per
vata o meno), in cui finalmente lo si informa che ha i
fare ciò viene in aiuto la funzione isLoggedl),
privilegi necessari per compiere operazioni che agli
nita in auth utils.inc.php. Potete vedere com'è
altri utenti sono precluse;
strutturata una tipica pagina protetta dando uno
headerl'Locatìon:
Tutto è nelle righe iniziali: se un utente vuole fare il
defi
sguardo al brevissimo sorgente di segreto.php. '.Ssite configt'login uri']. '7'.sessitmnamel).'='.session id());
furbo viene dirottato alla pagina di logout. Gestire l'uscita degli utenti dal sistema oltre che l'in
Abbiamo allo scopo utilizzato la funzione headert)
gresso è un altro momento importante: se ne occupa
di Php, la quale manda appunto un header di una
il file logout.php, che non fa altro che distruggere i
richiesta HTTP al browser: usando la dicitura
dati di sessione relativi all'utente, con la chiamata
"Location:
<URL
a
cui
saltare>", possiamo far sì
unset($ SESSIONE'utente'] ). Nella mia implemen
che il browser salti all'indirizzo che più ci piace.
tazione, il gestore di logout distrugge anche ta ses
Mi preme farvi notare come all'URL di destinazione
sione stessa, ma potrebbe essere troppo per le
abbia aggiunto i dati relativi alla sessione. Tenete
vostre necessità. Se così fosse basta eliminare la
inoltre presente che l'URL deve essere assoluto e
chiamata a session destroyO, ma di solito si prefe
completo, ossia comprensivo di http:// iniziale.
risce fare piazza pulita e ricominciare da capo...
~
La mia community in PHP! In questa puntata vedremo come utilizzare un database MySQL come
backend per l'autenticazione e la gestione degli utenti della nostra comunità in PHP. Luca Gambetta <l.gambetta<aUnuxprati<:o.Corn=
Li approccio scelto, quello dì basare il "regi
stro" degli utenti su di un file dì testo, se formalmente corretto ed utile per com
prendere i meccanismi che stanno alla base della
aggiungendo i dati per la connessione al database
gestione di una community. alla lunga tende a
all'array che contiene la configurazione:
mostrare tutti i suoi limiti, che risiedono principal
mente nelle prestazioni, nella manutenibilità e
ssite_config =
arrayl
nell'estensibilità del sistema di stoccaggio dei dati.
'dbname'
=>
'linu«pratica',
Occorre fare un passo più in là e giovarsi di tutte le
'dbuser'
=>
'Unuxpratico',
potenzialità di un serio motore per Basi di Dati, nel
'dbpass'
=>
'linuxpratico',
nostro caso l'arcinoto MySQL. L'integrazione dì
■dbnost'
=>
"localtiost',
quasi tutti i motori per database in Php è totale e molto solida, cosa che permette di solito di ridurre i passi da fare a poche, semplici chiamate a funzio ne: nel riquadro apposito potrete trovare il riferi
Utilizzeremo questi valori in tutte le successive ope
mento a quelle da utilizzare con MySQL, che sono le
razioni che faremo col database.
stesse utilizzate in queste pagine.
A questo punto dobbiamo mettere mano al file
Poiché un Database Server (d'ora in poi abbreviato,
auth.inc.php che, vi ricordo, viene incluso dalla
a seconda del contesto, in DB o DB Server) è,
nostra procedura di autenticazione (implementata
appunto, un server, ossia un programma che atten
in logìn.php) e sovrintende alle operazioni di
de una connessione mediante protocollo TCP/IP
gestione della procedura stessa.
lungo la quale scambiare i dati con una applicazio
Per connetterci al database utilizzeremo la funzione
ne client, nel nostro caso PHP. Stabilita questa con
dbConnectO, definita all'inizio dei file; analizziamola
nessione l'applicativo client fa interrogazioni sui
per intero:
dati utilizzando il linguaggio SQL, acronimo di Structured Query Language, che ci permette di
function dbConnectl)
esprimere concetti quali "prendi tutti i record in cui
global
il campo nomo abbia valore Unuxpratìco".
if
Per la cronaca quanto appena espresso ("Prendi
Sdb,
( !is_rescurce(Sdbl)
Ssite contigl'dbuser'l, return
FROM miatabella WHERE
nome
=
{
Sdb = @mysql connect(Ssite config['dbtiost ' ].
tutti...") si tradurrebbe in SQL con qualcosa tipo:
SELECT •
{
Ssite config;
'Unuxpratìco'
ISdb
!==
@mysql }
else
return
Ssite^conflgj'dbpass'));
false && select
db(Ssi.te_confìgl'dbname')));
true;
Come potrete notare la somiglianzà con un linguag gio "naturale" è molto accentuata, cosa che facilita non poco la costruzione di query che replichino
Innanzitutto essa include, grazie al costrutto
relazioni complesse.
global, le variabili globali Sdb e Ssiteconfig. Se
Palle parole ai fatti Dopo questa premessa mettiamo le mani sul codice,
per quest'ultima non c'è nulla da rilevare (racchiu de la nostra configurazione), per la variabile Sdb il
discorso è differente. In essa conserveremo la con
implementando la gestione degli utenti mediante
nessione corrente al database: in questo modo
MySQL. Per far ciò dobbiamo solo modificare poche
eviteremo di stabilire una connessione se ne sia già
funzioni, senza toccare per nulla la logica di funzio
attiva una. Avremo più chiaro questo discorso quan
namento: infatti, nella prima stesura, avevamo
do analizzeremo le funzioni che interagiscono col
preso degli accorgimenti perché un'operazione del
database degli utenti, nel frattempo ci basta sapere
genere risultasse del tutto indolore, cosa che in
che verrà utilizzata da tutte le funzioni successive.
effetti è (potete scaricare i sorgenti relativi a questo
In ogni caso dbConnectO verifica prima se esista
articolo facendo riferimento all'apposito riquadro in
una connessione e, nel caso non esista, ne stabili
queste pagine).
sce una, selezionando ovviamente anche il giusto
Innanzitutto modifichiamo il file conf ig . ine . php,
database- Basta perciò invocare questa funzione
per sapere se possiamo operare coi database.
con la ricca documentazione in rete.
Le fa da contraltare la funzione dbCloseO, che
La query SOL per scegliere un utente viene passata
come il nome lascia intendere chiude la connessio
come primo parametro alla funzione mysql
ne al DB in modo "pulito". La nostra attenzione
il secondo parametro che essa accetta è una varia
adesso va posta alle tre funzioni Identifica* ),
bile contentente la risorsa database corrente, che
Autenticai) ed Autorizzai). La prima, come
non è altro che il valore generato dalla chiamata a
detto, si occuperà di verificare se un utente con una
dbConnect().
determinata log in esista nel sistema. Le istruzioni
Nel nostro codice !e righe "incriminate" sono:
query{):
fondamentali di questa routine sono: if
((Sqi
Slogin - mysql_escape_string{Slogin):
» nysql query("5ELECT uid,
UNIX_TlHESTAKP(last.login) WHERE login ■
ìf
({Sqi
= mysql queryC'SELECT
uid,
UNIX TIMESTAMPUast login) WHERE
login =
as
login,
Sdb))
!==
false)
free
return
}
else
'$login'",
Jdb))
!==
false)
{
Che possiamo riscrivere, in modo più chiaro, così:
Ssql
=
"SELECT uid,
result(Sqi);
login,
passward,
UNIX TIMESTAHPUast
Jdati;
return
password,
{
Sdati - mysql_fetch arraylSqi. MYSQL ASSOC); mysql
login,
last_logìn FROM utenti
passwortì.
last login FROH utenti
■Slogin'",
as
FROH
utenti
login)
WHERE
as
login =
last
login
'Slogin'";
false;
Sqi
= mysql query(Ssql,
Sdb);
Potete notare come fin da subito applichiamo la
funzione mysql
escape stringi) alla variabile
if
(Sqi
!== false)
{
Slogin: è un passo importante, in quanto questa funzione si preoccupa di mettere un carattere di
La funzione mysql
backslash \, davanti a caratteri "particolari", come
se l'operazione non è andata a buon fine (di solito
ad esempio l'apostrofo, per far sì che possano esse
perché la query contiene degli errori), altrimenti
re inseriti senza problemi nelle nostre query.
ritoma un indice alla query corrente.
Così facendo possiamo scrivere software robusto:
Perché venga restituito un indice è presto detto:
ricordatevi che è bene non inserire mai direttamen
possiamo far eseguire al server più query; perciò
te il valore di una variabile proveniente dall'esterno
ognuna di esse verrà associata ad un indice, che
(ad esempio da una richiesta PQST) nelle query al
utilizzeremo, nelle successive chiamate alle funzioni
database, pena diverse vulnerabilità che vanno
per l'estrazione dei dati nel recordset.
sotto il nome di SQL-lnjection, un argomento molto
Ritornando al codice SQL della query, esso chiede
stimolante che vi consiglio di approfondire aiutandovi
di estrarre i campi chiamati uid, login, password e
query () ritorna il valore FALSE
INFORMAZIONI
II database
5e lavorate in locale, potete creare questo database facilmen
MySQL utilizzato
te dando i comandi:
II database di esempio si compone di una singola tabella, così
S mysqladmin
composta (trovate la definizione nel file dbutenti.sqi):
S tnysql
> uid integer not
nuli auto^increment
primary
key:
-u
-u
root
root
create
linuxpratico
Unuxpratico < dbutenti.sql
A questo punto avrete creato il database linuxpratico e
rappresenta CUserlD (UID) dell'utente, che ci servirà per
creato al suo interno la tabella utenti: non vi resta che impo
identificarlo univocamente:
stare i permessi d'accesso entrando nel client MySQL:
> login varchar(19)
not
nuli unique: è il campo che
contiene la login dell'utente, che deve essere univoco (ossia possiamo avere un solo utente con un certo nome) e
S mysql
-u
root
linuxpratico
non essere nullo, cosa che non vuoi dire che non possa
essere vuoto. Viene anche creato un indice su questo
tiysql» GRANT ALL ON linuxpratico.• TO tinuxpratico@T.ocalhost
campo, in modo da velocizzare le operazioni di ricerca; > password
char(3Z)
not
nuU: è il campo che contiene
l'hash MD5 della password: tali hash sono lunghi sempre 32 caratteri. Notate come nel campo le password vengano conservate in forma crittata: ciò per garantire una
maggiore sicurezza. Se un utente dovesse dimenticare la password basta generarne una, salvarla nel DB, inviargliela e dagli poi ia possibilità di cambiarla; > last
login datetirae: contiene ora e data dell'ultimo
accesso dell'utente al sistema.
Sono solo i campì minimi di un sistema di gestione utenti: vi consiglio di costruire i vostri aggiungendo altre informazioni,
quali l'E-Maìl dell'utente, un suo recapito, una sua descrizione e così via.
22
IDENTIFIED
by
'Unuxpratico1;
nysql> FLUSK PR1VILEGES;
nysql> quit
Questi comandi autorizzano l'utente l muxprat irò, con una con
nessione da locai host ad accedere al database Unuxpratico,
utilizzando la password Unuxpratico. Nulla vi vieta di cam biare sia utente che password, ricordandovi di aggiornare il file config.inc.piip.
Nel caso invece abbiate un hosting con la possibilità di usu
fruire dì un database, sicuramente avrete anche l'accesso ad un pannello di controllo tipo PhpMyAdmin: in questo caso
basta fare l'upload della query utilizzando l'apposito comando del programma.
Terminare il lavoro
last login dalla tabella utenti, ma solo dai record in cui il campo Login sia uguale al valore che speci
A questo punto abbiamo implementato interamente
fichiamo: nel nostro caso il campo deve essere
la funzione Identifica() in modo che restituisca
uguale al valore della stringa contenuta nella varia
un array di valori esattamente come la nostra pro
bile Slogin. Notate una partico!arità: estraiamo il
cedura di autenticazione se l'aspetta. Per nostra
campo lastlogin trasformandolo in un timestamp
fortuna la funzione Autenticai ) è del tutto invaria
Unix. Se non facessimo così, ci troveremmo con una
ta e quindi spostiamo l'attenzione sulla funzione
data nella forma YYYY-MM-DD
Autorizzai ), che è un altro punto importante della
hh:mm:ss, ossia
"anno-mese-gtorno ore:minuti:secondi" come
nostra procedura di gestione degli utenti.
2004-03-25
Al solito, viene stabilita una connessione al DB e
03:20:10, che dovremo trasformare in
verificata la correttezza dei parametri passati.
ogni caso per poterla poi manipolare. Lasciamo compiere questa operazione a! DB Server, in modo
Eccoci giunti al cuore della funzione Autorizzai ): è
da migliorare le prestazioni ed avere da subito il
di nuovo una query SQL al database a farla da
tipo di dato che ci occorre.
padrona.
Verificato che la query sia andata a buon fine dobbia
Grazie ad essa salviamo i dati dell'ora dell'ultimo
mo prelevare i dati estratti dal database: per fare ciò
accesso dell'utente al nostro sito:
utilizzeremo la funzione mysql fetch arrayO, che ritorna una riga di dati (ovvero un record del DB),
St = tineO;
mettendola in un array e preoccupandosi anche di
ìf
inserire delle chiavi con nome pari a quello del
(mysql queryl'UPDATE utenti SET last_login FROH UNJXTIME(St)
WHERE uid
campo estratto. La funzione accetta due parametri,
=
" . Strval(Sdat1['uid']), Sdb)
il primo, necessario, che indica di quale query
Sdatil'last
login']
■
!==
false)
{
st;
dDCloseO; retimi
INFORMAZIONI
}
Giocare con le date
ttv
Sdati;
else dbCloselI ;
Innanzitutto associo alla variabile St il valore intero (come timestamp) dell'ora attuale; successivamente
Per trasformare un campo di tipo data MySQL in un timestamp
potete utilizzare la funzione Php strtotime( ). Per migliora
utilizzo questo valore nella query, che, estrapolata
re le prestazioni è però meglio fare svolgere tali operazioni
dal contesto è:
a MySQL, che offre un completo set di funzioni per la mani polazione delle date.
J
UPDATE utenti
SET last login =
FROM UNIXTIME(St)
WHERE uid = ".strval(Sdati['uid']l
vogliamo i risultati, il secondo, facoltativo, il formato
Che vuoi dire: aggiorna la tabella utenti impostan
dei dati stessi. Stando alla nostra query avremo per
do il campo last
ciò un array così composto:
ma solo per il campo in cui uid è pari al valore di
login al valore del timestamp St,
Sdatifuid']. In seguito aggiorno l'array contenente i dati utente
arrayf 'jid'
=>
un
numero intero,
col timestamp che abbiamo salvato e chiudo la con
Indenti!icativo
univoco dell'utente 'login'
=> una stringa,
'password'
=>
'last login'
l'nash
=> un
md5
intero
perazione, dato che a questo punto non ne ho più
della password
contenente
il
nessione al database. Vi faccio notare come io chiu da la connessione a) DB qualunque sia l'esito dell'o
il nome utente
tiroestamp
dell'ultimo
accesso
bisogno (anche perché la connessione verrebbe comunque chiusa al termine dell'esecuzione dello script PHP).
A questo punto il nostro sistema di autenticazione Quando la funzione mysql fetch arrayO restitui
si basa finalmente su database ed è pronto ad ospi
sce una riga, si preoccupa di portarsi al record suc
tare anche migliaia di utenti.
cessivo. Ciò vuoi dire che se la query restituisse
Come avete visto, per fare questo passaggio impor
cento valori, con la prima invocazione estrarremo il
tante abbiamo dovuto cambiare circa una cinquan
primo, con la seconda il secondo e cosi via, fino ad
tina di righe di codice, con un risparmio di tempo,
ottenere FALSE quando non ci siano più record nel
grazie agli accorgimenti presi nella prima stesura
l'insieme dei risultati {recordset) da poter estrarre.
del codice stesso, davvero notevole, visti i risultati.
La comodità dell'utilizzo di questa funzione sta anche nel suo secondo parametro, che ci permette
Estendere e ritoccare
di forzare il tipo di array ritornato, a seconda della
Grazie al timestamp salvato nel database possiamo
costante che gli passiamo: con MYSQL ASSOC otter
implementare una funzione molto semplice ed utile:
remo un array associativo; con MYSQL NUM un array
un conteggio sul numero degli utenti attualmente
con solo chiavi numeriche e con MYSQL BOTH un
online. Il principio su cui si basa la soluzione propo
array sia associativo che numerico.
sta è che ci basta contare quanti utenti siano loggati
Estratti i dati ci preoccupiamo di liberare la memoria da
entro un certo lasso di tempo. Ecco la query che
esso occupata invocando mysqlf ree resulti )■
facciamo in utentiOnline( ):
INFORMAZIONI
"amministratori" e "utenti normali" (ovviamente se volete dividere gli utenti in gruppi o gestire in modo
Le funzioni utilizzate
più granulare gli accessi il discorso si farà più com plicato, esulando dagli scopi introducivi di questa
Nel corso dell'articolo abbiamo utilizzato le seguenti funzio
ni MySQL (vengono indicati tra parentesi quadre i parametri facoltativi). Si ricorda che non sono stati elencati né tutti i parametri che le funzioni accettano, né tutte le funzioni pos
sibili, per le quali si rimanda al manuale di PHP che trovate nel sito http://wrfm.php.net:
serie di articoli). Ritocchiamo subito la tabella del database aggiungendo il campo accesso, che potrà contenere solo i valori admin e user, rispettivamen
te per indicare un utente "amministratore" ed uno "normale". Date le seguenti istruzioni SQL utilizzan
do o il client mysql a riga di comando o il classico
resource mysql connect(host,
utente,
password):vi
PhpMyAdmin:
permette di connettervi ad un server DB MySQL. Ritorna
una risorsa al database o il valore FALSE se non è stato pos sibile connettersi.
ALTER TABLE utenti
ADD accesso ENUH('admin','user') HOT
bool mysql select db(database [, db resource]): seleziona il database su cui operare sul server MySQL indi cato da db_ resoli ree. Se questo parametro non è presente viene utilizzata l'ultima connessione stabilita. resource mysq\ query(query sql
[, db resource)}:
Ora non ci
NULL DEFAULT
'user';
resta che ritoccare la funzione
Identif ica( ) per far sì che venga prelevato anche questo nuovo campo: editate perciò la query:
esegue la query SQL specificata, ritornando FALSE se si è
verificato un errore o un indice di query utilizzabile nelle successive chiamate a mysqlfetch*. La query viene
SELECT uid.
login,
password.
UNIX TIMESTAHP(lastlogin)
as last login FROH utenti WHERE login = 'Slogia'
~
eseguita sul DB server specificato o sull'ultimo a cui ci si è connessi.
Facendola diventare:
array mysqlfetch arraytquery index [, result type]): estrae un record generato dalla query indicata da query index, facendo avanzare il puntatore interno della
SELECT uid.
login,
passworfl,
accesso,
UNIX TIHESTAMPUast login] as last. login
query. Ritorna FALSE se non ci sono più dati da estrarre. Si
FROM utenti WHERE
può cambiare il tipo di array ritornato passando come
login =
'siogin'
secondo parametro una delle costanti MYSQL ASSOC. MYSQL NUM o MYSQL BOTH, per ottenere un array assodativo,
Anche in questo caso non dobbiamo editare nes-
numerico o con entrambe le chiavi.
sun'altra funzione: il sistema di autenticazione fun
bool mysqlf ree_ resulti iquery index) ): libera la
zionerà senza problemi, permettendoci di avere que
memoria associata ad una query.
sta caratteristica aggiunta in poco più di 2 minuti!
bool mysqlclosef[db server]): chiude la connessione al
Adesso sta a voi scegliere cosa fare con gli utenti:
server specificato, o all'ultimo server a cui ci si è connessi.
verificando il valore del campo accesso dell'array
string mysql_escape string(stringa): ritorna una strin
S SESSIONI 'utente' ] (che contiene i dati dell'uten
ga con caratteri opportunamente trattati per essere immes
te correttamente loggato) potrete ad esempio redi
si in una query SQL. Di solito viene aggiunto un carattere di backslash davanti a caratteri come ad esempio l'apostrofo. string mysql errori): ritorna una stringa contenente l'errore generato dall'ultima operazione con server MYSQL.
rigere direttamente ad un pannello di controllo "per pochi intimi". Ricordate sempre che il valore di accesso è una stringa, e come tale va tratta nei vostri script.
Per concludere SELECT COUIJT1-)
as
e
FKOM utenti
Cos'altro aggiungere? Un solo consiglio: tenere
WHERE
>=
sempre in mente la sicurezza. Purtroppo, infatti, il
1886
web è un mare ricco di sorprese impreviste ed è
UNIX TIHESTAMPflast login) UNIX TIMESTAMPinowf))
-
~
quindi meglio non fidarsi di nessuno: vanno control Grazie ad essa contiamo tutti i record per cui il timestamp del campo last
login sia maggiore o
uguale al timestamp della data e ora correnti meno
no sotto forma di variabili GET o POST prima di utiliz zarli coi database o anche solo nelle funzioni.
1800 secondi, ossia mezz'ora. E' importante notare
Un passo falso potrebbe portare alla corruzione di
come vada estratto questo valore chiamandolo e
un intero database, cosa assolutamente spiacevole.
(count(')
24
lati più e più volte tutti i dati che arrivano dall'ester
e), di modo che possa trovarlo con
Nei sorgenti sono presenti anche due funzioni per
tale nome nell'array che verrà restituito da
as
creare e rimuovere un utente: sono rispettivamente
mysql
aggiungiUtente()
fetcharrayl). L'uso sapiente dei costrutti
e
rimuoviUtente{ ).
Sono
listo ed each(), permette in un colpo solo di met
migliorabili in tanti punti; soprattutto, come potete
tere questo valore nella variabile sconta, che diver
vedere, esse non fanno nessun controllo preventivo
rà il valore di ritorno della funzione.
sui dati, nonostante le raccomandazioni poc'anzi
Abbiamo utilizzato una tabella che definisce gli
enunciate: non è una svista, in quanto per tali con
utenti molto semplice: mancano infatti diversi
trolli basta la funzione loginValido( ), definita in
campi che sarebbe utile inserire, quali ad esempio
auth utils. ine . php. Quando realizzate il modulo
il nome dell'utente, la sua E-Mail, i suoi privilegi
(HTML Form) per la registrazione, ricordatevi quindi
d'accesso.
di controllare tutti i campi che verranno passati alla
Potremmo decidere infatti di separare gli utenti in
sua sottomissione dall'utente che vuole registrarsi.
base ad un grado di accesso al sistema, ad esempio
Cos'altro aggiungere se non... buon hacking!
""
PHP e database: ottimizzare le connessioni In queste pagine approfondiamo la conoscenza delie funzioni riguardanti Mi/SQL e l'utilizzo del linguaggio SQL, in particolare cercando di evitare alcune pratiche di programmazione.
Luca Balzerani <l.balzerani@linuxpratico.com>
Avevamo concluso l'artìcolo precedente mostrando una prima soluzione per l'acces so ai record restituiti da una interrogazione (o query) SQL. L'esempio di codice che avevamo
Come si vede, accedere al campo descrizione non
proposto era il seguente:
richiede di conoscere la posizione di tale colonna.
if
to il nostro compito sia semplificato dall'uso di
Dovrebbe essere facile, quindi, convincersi di quan {$risuUato)
while echo
(
(Srecord = mysql_fetch_row(srisuUato)) "Codice:
"
.
Srecord(O)
echo "Descrizione:
"
.
.
"
-
SrecordUl
mysql_fetch_array( ). Per completezza segnaliamo
{
anche una seconda
"; .
variante della funzione
mysql_fetch_row(), mysqlfetchassoct), che
"<br>";
restituisce solo la parte associativa delì'array (per
cui si può accedere ai campi solo per nome e non anche per posizione).
In tale frammento, in cui - come il lettore ricorderà
Il listato 1 ripropone lo script di esempio che conclu
- la variabile srisultato contiene il valore ottenuto
deva l'articolo precedente, modificato in modo da
dall'invocazione della funzione mysql queryO, il
accedere in modo nominale ai campi dei record.
record corrente viene prelevato mediante la chia mata a mysql
fetch_row() ed assegnato all'array
5record. Quest'ultimo conterrà un elemento per
Dimensione dei
record set
ognuno dei campi (o colonne) del record, a cui si potrà accedere nella consueta modalità posizionale.
L'appetito, si sa, vien mangiando,
Dall'esempio mostrato si comprende, tuttavia, che
che sappiamo eseguire comandi SQL sul nostro
per cui
ora
accedere ai campi di una query attraverso la loro
database e siamo in grado di accedere ai risultati
posizione (cioè Srecord[0] perii primo. Srecord[1]
prodotti dalle interrogazioni, vogliamo arricchire
per il secondo e così via) è piuttosto scomodo: ad
ulteriormente il nostro bagaglio di conoscenze.
esempio, se ogni record corrisponde ad un libro, per
Introduciamo, allora, due nuove funzioni della libre
accedere al nome dell'autore piuttosto che al codi
ria MySQL che ci permettono di conoscere le dimen
ce ISBN dovrò necessariamente conoscere la posi
sioni degli insiemi di record su cui stiamo lavoran
zione di tale campo. A questo indubbio disagio si
do. Quando eseguiamo una query siamo interessati
aggiunge un'altra considerazione di importanza
a sapere, infatti, quanti record abbiamo ottenuto
ancora maggiore: l'accesso posizionale ci costringe
con tale interrogazione (senza doverli scorrere e
a modificare il codice se ci troviamo a dover altera
contare uno alla volta); analogamente siamo inte
re l'ordine dei campi.
ressati a sapere, ogni qualvolta eseguiamo dei
Per ovviare ai problemi sopra citati utilizziamo, allo
comandi SQL di inserimento, modifica o cancellazio
ra, una variante della funzione mysqlfetch
ne, quanti record sono stati coinvolti nell'operazio
row( )
e precisamente mysql_fetch_array(), la quale si
ne. Le funzioni che rispondono a queste due esigen
comporta esattamente allo stesso modo salvo il
ze sono, rispettivamente, mysq\_num_ rows ( )
fatto che restituisce il record corrente sotto forma di
mysql affectecl
array associativo. In questo modo, oltre ad essere
esempio pratico.
referenziabili in base alla posizione, è possibile
Supponiamo di volere conoscere il numero di pro
accedere ai campi anche nominalmente.
dotti inseriti nel nostro database dì prova. Abbiamo
Chiariamo questo aspetto riscrivendo il frammento
a disposizione, come sempre, varie possibilità; la
di codice precedente.
più istruttiva dal nostro punto di vista è quella di
e
rows( ). Vediamo per entrambe un
effettuare un'interrogazione che estragga tutti i if
(Srisultato) while
record della tabella prodotti per poi contare, grazie
{
(Srecord
= mysql.
echo
"Codice:
echo
"Descrizione:
fetch array(Srisultato))
Srecordl'codice')
-
{
";
a mysql num rows{), il numero di record ottenuto. Il frammento di codice è il seguente:
Jrecordl'descrizione']<br>"; //
Query che estrae tutti
t
record
INFORMAZIONI
le funzioni utilizzate
Restituisce il numero di record (cioè righe) ottenuti dall'ultima query 5QL eseguita.
Di seguito presentiamo un riepilogo delle funzioni della libreria MySQL utilizzate nell'articolo. Per ogni funzione riportiamo una
Srisultato: l'identificativo del risultato prodotto da
breve descrizione e la spiegazione dei parametri in input e del
un'invocazione della funzione mysql query{ )
risultato restituito.
mysql^affected rows{]
fnysq*_fetch_array[}
m>rsql_3ffected_ rows (Srisultato)
Simile alla funzione mysqlnum rows ( ). restituisce il numero Restituisce il record successivo della query eseguita, se dispo
di record interessati dall'ultimo comando SQL di tipo INSERT.
nibile, oppure il valore FALSE se non vi sono altri record da
UPDATE o DELETE eseguito.
restituire. Nel primo caso il record è fornito sotto forma di un array associativo i cui elementi sono coppie chiave/valore in
Srisultato: l'identificativo del risultato prodotto da
cui la chiave corrisponde rispettivamente al nome ed al valore
un'invocazione della funzione mysql queryl )
di ogni campo della query. I campi sono accessibili anche in
mysql Error[]
modo posizionale. Srisultato: l'identificativo del risultato prodotto da
mysql_errori Sconnessione)
un'invocazione della funzione mysql query( ) Restituisce la descrizione testuale dell'ultimo errore MySQL
mysql fetch assoe[]
verificatosi o la stringa vuota se non è avvenuto alcun errore.
~
Sconnessione: l'identificativo della connessione MySQL; è
mysql fetch assoc(Snsultato)
Analoga alla precedente, salvo il fatto che l'array restituito è puramente associativo per cui i campi possono essere referen
il valore ottenuto da mysql_connect( ) al momento della connessione
mysql errnof]
ziati solo per nome e non per valore.
Srisultato: l'identificativo del risultato prodotto da
mysql errno(Sconnessione)
un'invocazione della funzione mysql_query( ) Restituisce il codice identificativo dell'ultimo errore MySQL
mysq!_mim_raws[J
verificatosi o il valore zero se non è avvenuto alcun errore. Sconnessione: i'identificativo della connessione MySQL
mysql_num_rows(Srisultato)
$sql
= "SELECT
*
FROM prodotti";
if
(Srisultato]
{
echo "Ho eliminato //
Esecuzione del
Srisultato
Se
if
(Srisultato)
l'esito è
.
"Nel
,
= mysqlquerylSsql,
//
echo
comando
positivo,
■
raysqlaffected_rows(Srisultato 1
.
" prodotti.";
Sconnessione);
stampo
il
numero di
record
Nel caso avessimo voluto conoscere il numero di record interessati in operazioni di inserimento o di
{
database
ci
sono
modifica, avremmo scritto del codice assolutamen
"
mysql num_rows(Srisultato)
.
" prodotti.";
te analogo. E' bene richiamare l'attenzione del let tore sul fatto che sia la funzione mysql_num_rows( ) che la mysqlaffected
rows() forniscono esclusi
Supponiamo adesso, invece, di voler eliminare tutti
vamente informazioni relative all'ultimo comando
i record della tabella prodotti aventi un codice
eseguito (nei rispettivi ambiti di competenza), per
inferiore a 100; se vogliamo sapere, dopo aver ese
cui se si deve eseguire una serie di operazioni -
guito il comando, quante righe della tabella sono
per le quali si vuole conoscere il
state eliminate, ovvero quanti prodotti sono stati
record coinvolti - sarà necessario invocarle dopo
cancellati dalla tabella, possiamo utilizzare ìa fun
ciascuna di esse.
zione mysql af fectedrowsf ) nel modo seguente:
//
Comando
//
dei
Ssql
=
di
eliminazione:
prodotti "DELETE
con
codice
FROM prodotti
WHERE
SQL di tipo statico, cioè comandi che restano immu
1B6
codice
SQL dinamica Fino ad ora abbiamo sempre considerato comandi
cancellazione inferiore a
numero di
<
1Q0";
tati ad ogni esecuzione della nostra applicazione
PHP. In realtà si tratta di una situazione che si verifi //
ca solo raramente nelle applicazioni reali; del resto
Esecuzione del comando
Srisultato = mysql query($sql,
Sconnessione);
è facile comprendere che, se non fosse possibile costruire in modo dinamico i comandi SQL da ese
//
Se
il
comando
ha
avuto
esito
positivo.
guire, ogni applicazione potrebbe effettuare solo un numero prefissato di operazioni. La costruzione e
~
l'utilizzo di istruzioni SQL dinamiche è, insomma, la
eliminazione di record usato in precedenza:
regola più che l'eccezione. Costruire in modo dinamico, cioè a tempo di esecu
DELETE
FROM
prodotti WHERE
codice
<
1G6
zione, le istruzioni SQL da utilizzare è in verità un compito semplice e allo stesso tempo molto rischio
II comando, come abbiamo visto, elimina tutti i
so. Un comando SQL. come abbiamo visto, non è
record della tabella prodotti aventi un codice infe
altro che una stringa e, in quanto tale, può essere
riore a 100. Si tratta, evidentemente, di un coman
manipolato a piacimento prima di essere eseguito.
do statico, in quanto se decidiamo, ad esempio, di
In particolare, ed è il caso più frequente, nella strin
eliminare i prodotti con codice inferiore a 200. dob
ga possono essere inseriti dei frammenti di codice
biamo necessariamente modificare il comando SQL.
SQL determinati in base all'input fornito dall'utente.
Possiamo rendere dinamico tale comando utilizzan
Si pensi, per avere degli esempi concreti, al caso
do come valore-soglia non un numero prestabilito
della ricerca per parola all'interno di una tabella: le
bensì il contenuto di una variabile. Esaminiamo ii
parole chiave specificate dall'utente diventano
seguente frammento di codice PHP:
parte integrante della query SQL; o ancora all'inse rimento nel database di dati forniti dall'utente. E'
Ssql
=
"DELETE
FROM prodotti
WHERE
codice <
Ssoglia";
chiaro che tutte le informazioni provenienti "dall'e sterno" devono essere opportunamente gestite
In questo caso ii comando effettivamente eseguito
prima di essere inserite all'interno di un comando
dipende dal valore della variabile ssoglia, che
SQL; in caso contrario il rischio è, nella migliore
potrebbe essere stata impostata precedentemente
delle ipotesi, quello di ottenere un comando non
ad un valore prefissato o magari provenire da una
corretto e quindi un errore; nel caso peggiore, inve
form HTML;
ce, si potrebbe configurare un vero e proprio attac co di tipo SQL injection, in cui un utente malintezio-
Ssoglia =
S REQUESTI'soglia' ];
nato immette informazioni costruite ad arte per
eseguire comandi arbitrari sul nostro database.
Dovrebbe essere chiaro che se ci limitassimo ad
Esaurita questa premessa, forse un po' ostica ma
inserire il contenuto della variabile Ssoglia senza
certamente doverosa, passiamo a considerare
alcun tipo di controllo, spalancheremmo le porte ad
concretamente degli esempi di comandi SQL dina
eventuali malintenzionati, i quali - come si è detto -
mici. Riprendiamo, per semplicità, il comando di
potrebbero costruire ad arte il valore del parametro
LISTATO 1
Lo script di esempio
ectio "Tabella creata con successol«Or>"; } else ( echo "Inpossi bile creare
//
parametri
inonehost
per
la
la tabella;
". «yiql.errori!,"<br
conni
• "localnost";
Sno»edb • "test";
II
Snoneutente -
Siql
'imi":
inserimento di un - 'INSEHT
VAUIESU.
ìp»ss«rd • "*;
record nella
tatuila
INID orodottilcodlce.deicriMonel
-Computer nodello XYZT;
ectio "Sto effettuando la connessione... "; Sccnresslone
-
nysal
tonnect linwwhost.
Inoneutente.
Soasiwcrfll.
if
(Bysglauerylssql.
Sconnessione!)
ecno "Record inserito con if
('sconnessionel
e\se
{
?cho
"Connessione
} else
f
[
rluscitalebr»": //
il
{
succesio!<0r
(mysql.seicct.ablJnomMDM
{
visualizzazione
Ssql
= "SELECT •
ecno
"Sto
record
FROK proUotll";
eslraenda
1
) else!
ione) ;
diel"Impossibile selezionare il database:
".Bysql_error());
If
CSrisultatQ)
( rori!;
}
else {
// creaiione tabella
'prodotti'
ectio "Visualizzazione:<br>";
isql
prodotti
while
-
"CREATE TABLE
codice
(
INT.
(Jrecord - nysijl felch_arr»y(SrlsuHato))
ectio "Codice:
descrizione VA«CHARi6D)
"
.
irecord[ 'codice' ]
NOI NJLL.
KEY(codice))';
echo "Sto creando la tabella... *; if
Isysql flueryitSQl.
Jconnessione))
{
■ysqWlosel Sconnessione) :
.
"
•
":
(
Ssoglia in modo da eseguire comandi arbitrar!. Nel
stato neutralizzato:
caso che stiamo esaminando la situazione è facil mente gestibile in quanto ciò che ci aspettiamo è
INSERT INTO prodotti(codice,descrizione)
un numero intero, per cui possiamo forzare una
VALUES (2,
'Unitay disco^)
conversione di tipo nel modo seguente: Esiste, ovviamente, anche la funzione inversa di Ssoglia = intval($_REQUEST['soglia']);
addslashesO, stripslashesO. che rimuove tutti i caratteri slash aggiuntivi.
L'uso della funzione intvalO ci garantisce che il
Abbiamo così completato questa breve panoramica
valore assegnato a $soglia è un intero, indipente-
sulla creazione dinamica di comandi SQL, un argo
mente dall'input.
mento di importanza tale da non poter essere trat
Se quest'ultimo non consistesse di un intero, ma di
tato in modo esaustivo in questa sede.
una stringa arbitraria, intvalO procederebbe
Come si è voluto sottolineare, comunque, le insidie
comunque ad una conversione coattiva.
non mancano ed anzi impongono al programma
La questione diventa poco più complessa quando
tore la massima attenzione rispetto alla sicurezza
abbiamo a che fare con delle stringhe. In casi del
dell'applicazione.
genere dobbiamo accertarci che esse non conten gano caratteri a cui MySQL attribuisce un significato
speciale; caratteri, in altre parole, che potrebbero
essere sfruttati a scopi poco salutari. Ne è un esem pio significativo l'apice singolo, il cui significato spe
Prima di concludere è opportuno presentare altre
ciale per MySQL è quello di separatore di stringhe.
due funzioni della libreria MySQL, funzioni che si
Consideriamo, a titolo di esempio, il seguente
riveleranno certamente indispensabili nello sviluppo
comando SQL che inserisce un record nella tabella
di qualsiasi progetto. Si tratta di mysql_error() e mysql errnoO, due funzioni che possono essere
prodotti.
invocate al verificarsi di un errore SQL per identifi INSERT INTO prodotti(codice.descrizione) VALUESd,
'Computer modello XYZ')
carne la natura. Abbiamo visto, infatti, che le fun zioni della libreria MySQL ci informano, con i valori restituiti, dell'esito delle operazioni cui sono pre
Volendo rendere dinamico tale comando procedere
poste; in tal modo siamo in grado di verificare, nei
mo come nel caso precedente, sostituendo ai valori
nostri script, la buona riuscita di tutte le chiamate
statici dei riferimenti a variabili PHP.
di funzione.
Quando però si verifica un errore abbiamo bisogno $sql = "INSERT INTO prodotti(codice,descrizione) VALUES(Scodice,
'Sdesc rizione')";
di informazioni circa l'errore stesso (che si tratti di
un errore sintattico, di un riferimento ad un campo o ad una tabella inesistente, etc.) che ci permetta
Ancora una volta tali variabili potranno essere forni
no di individuarlo e correggerlo.
te da un utente attraverso una form e dovranno
Le suddette funzioni assolvono tale compito, resti
pertanto essere adeguatamente validate. Mentre il
tuendo rispettivamente la descrizione testuale ed il
caso della variabile Scodice, che è un campo
codice (univoco) dell'ultimo errore verificatosi. Se
numerico, è perfettamente analogo a quello visto in
solitamente la descrizione testuale (destinata alle
precedenza, per $descrizione, che è un campo
persone) consente di risalire immediatamente alla
testuale, dobbiamo ricorrere ad un'altra funzione:
natura del problema, una gestione programmatica
addslashesO. Quest'ultima si occupa di neutraliz
di situazioni di errore farà uso dei più rigorosi codici
zare eventuali caratteri dal significato speciale
di errore, il cui elenco può essere consultato al
anteponendo ad essi una backslash. Supponiamo,
seguente indirizzo web:
ad esempio, di voler inserire un record la cui descri
http : //dev. mysql. com/doc/mysql/en
zione è Unita'
/Error-handling.html
disco. Se inserissimo direttamente
tale stringa nel comando SQL otterremo qualcosa del genere:
Nelle due puntate di questo articolo abbiamo impa INSERT INTO prodotti(codice,descrizione) VALUES(2,
'Unita'
disco')
rato a stabilire un collegamento con un database MySQL da una applicazione scritta in PHP, mostran
do le procedure per l'esecuzione di comandi SQL e Come si vede, la presenza dell'apice all'interno
per il recupero dei risultati delle query, fino ad
della stringa provoca un errore sintattico, in quanto
accennare all'argomento, importante e delicato,
MySQL considera la stringa terminata dopo la paro
della costruzione dinamica del codice SQL.
la Unita. Usando, invece, la funzione addslashesO
L'importanza dei temi trattati è tale da meritare
possiamo aggirare il problema:
certamente un approfondimento maggiore di quello
Sdescrizione = addslashes(S_REOUEST['descrizione']);
di, è quello di continuare il proprio percorso alla
proposto in questa sede. L'invito per il lettore, quin
scoperta delle grandi possibilità offerte dal connu La stringa SQL risultante sarà la seguente in cui,
come si nota facilmente, il carattere speciale è
bio PHP/MySQL.
PHP ed E-Mail: inviare messaggi via script Con la classe phpmailer è possibile inviare in modo semplice ed effica ce messaggi E-Mail semplici, con allegati e perfino formattati in HTML: vi spieghiamo come utilizzarla.
Luca
Balzerani <l.balzerani@linuxpratico.CQm>
In questo articolo ci occuperemo di phpmailer una classe PHP che consente di inviare messag
gi di posta elettronica complessi, caratterizzati dalla presenza di allegati e dalla possibilità di utiliz
incl.ut)e(11<percor50>/class.pnpmail.er.plip1');
zare anche il formato HTML.
in cui il segnaposto <percorso> deve essere sosti
Introduzione:
tuito dal percorso in cui abbiamo precedentemente
perché phpmailer?
copiato i file. A questo punto siamo già pronti per il primo utilizzo di phpmailer; vediamo, allora,
II fulcro di questo articolo, come è stato già antici
passo per passo, come procedere per l'invio di un
pato, è phpmailer, una classe PHP per l'invio di
messaggio.
messaggi di posta elettronica. Le principali caratte
La prima cosa da fare, essendo phpmailer una clas
ristiche che rendono interessante tale classe, e che
se, è crearne un'istanza, come mostrato di seguito:
ci spingono ad utilizzarla in luogo delia funzione nativa mail() messa a disposizione da PHP. posso
//
no essere così riassunte:
Smail = new phpmailerli;
> phpmailer consente di costruire con facilità
Da adesso in poi opereremo sempre su tale istanza,
creazione
di
un'istanza di
phpmailer
messaggi E-Mail con allegati fil cui contenuto
impostandone le proprietà ed invocandone i meto
può provenire da file o da stringhe);
di. Il primo metodo che eseguiamo è lsSMTP( ), che
> è possibile spedire messaggi sia nel tradizionale
dispone di utilizzare, quale metodo di spedizione
formato testuale sia in HTML, sia in entrambi (in
del messaggio, il protocollo SMTP. Si noti che non si
questo caso si parla di messaggi multipart);
tratta di una scelta obbligata in quanto phpmailer
> sono supportate diverse modalità per l'invio dei messaggi: phpmailer può utilizzare la funzione
supporta anche altre modalità di spedizione; dal nostro punto di vista, tuttavia, è più educativo uti
nativa mail{ ), dialogare direttamente con qmail
lizzare SMTP in quanto si tratta di un protocollo che
e Sendmail (i più diffusi MTA, Mail Transfer
ci consente di dialogare con qualsiasi MTA (in pro
Agent) o utilizzare il protocollo standard SMTP.
posito si veda il riquadro 1). Una volta stabilito di usare SMTP dobbiamo anche specificare il nome del-
A ciò aggiungiamo, come spunto intrigante per gli
l'host del relativo server, assegnandolo alla proprie
utenti più smaliziati, che la classe ausiliaria SMTP,
tà SHost della nostra istanza.
inclusa nella distribuzione di phpmailer, può essere adoperata in altre applicazioni per l'autenticazione
//
seleziona
degli utenti.
//
come modalità di
La versione di phpmailer a cui si farà riferimento
Smail->I5SMTP();
il
protocollo
SHTP
spedizione
nel seguito è la più recente disponibile al momento della stesura, e cioè la 1.72, liberamente scaricabì-
//
nome dell'host
del.
server
SMTP
le, secondo licenza GPL, dal sito ufficiale su SourceForge: http://phpmailer.sourceforge.net
RIQUADRO 1
Primi passi L'installazione non presenta alcuna difficoltà: è suf
ficiente decomprimere l'archivio scaricato (ZIP o tgz) e copiarne il contenuto in una cartella del nostro spazio web, locale o remoto. Per utilizzare phpmailer in una pagina PHP sarà sufficiente inclu dere
il
file
principale
della
distribuzione
(class. phpmailer, php) con la seguente istruzione:
MTA Con il termine Mail Transfer Agent (abbreviato in MTA) si indi cano i software che si occupano della trasmissione dei mes saggi di posta elettronica, spesso chiamati anche mail server. I protocolli Internet più utilizzati da queste applicazioni sono P0P3 per la ricezione di posta e SMTP per la spedizione.
Tra i server SMTP più diffusi ricordiamo lo storico Sendmail, qmail ed Exim.
LISTATO 1
ki Un esempio d'uso <td>NoiM Bel
•heatì>
<title>Invin messaggi
<ttì>«input
con phpmailer</utle>
irlttcnto:</tlt>
typc'text"
name-'FromName"
size»"4S"
</head> <body> <?php
/■ • mailer.php
>E-iwil nitlente:</ttì*
(script principale)
xinput * Se e' * con
stato premuto il
l'invio del
tasto
"Invia11
type-'text" name»"from-
?>*»</td>
messaggio
<td>Home del
ìf
sne^-40-
value="-:?= htmlspeciaUdarsIs REQJEST]'From1 ])
si procede
IS_HEQUEST[Invia'|>
*td><input
(
desti nata rio:*/td>
type="text"
naine-'ToNanie"
size="49"
value="<?= htmlspacialcnars(S_REOUEST[ ToName']l
7>"x/tda
include I "p(iproailcr.l.7?/cla55.phpmailer.php"); Snail • new phpraailerf) ;
// Metodo di
<ta>E-mail destinata no :</id> «ttì>=inpijl
spedizione
Smail->IsMAIK);
=
-
S_REQUESTi ■FromNaiw11 ;
«dxinput
type="text"
name=J5uoject"
5ize="40"
value="<7- htmlspecialchars(Ì_REOLESTl'Subjecf1I
Destinatario
Oggetto e
size="4B"
</tr=
Smail->flddfitìdresMS,RE0UE5T['To']. //
na:ne="To"
S_REQUESTf'FronT |;
Naw
//
type-"text"
ualue="<?= htmlspecialchars|S_RE0JE5T['To11
S_REQUEST|'ToNarne']) ;
reslo del messaggio
Smail-»Subject = S_REQUEST[-Subjecf]:
<tdxtextarea name=MMessage"
Smail->8otìy = S_REOliEST['Kessage'];
rows="7"
CDls^-^e11»
*7= htnlspecialchar5(S_RE0U£ST[ rMes5age' ] 1
</tr> //
formato
(tasto o HTML)
smail->IsKTHL = if
(boolean]
(inaii->IsKTHL)
$_RE0UEST[■FormatohTML'];
$nail-*AUBody -
«tdJ-e/t*srrip_tag5(S_RE0UESTI1Message1]l;
heckboi:"
<td>-:input
naire-'FomiatoHTML"
S.REOUESTCForjmoHTML1!
If ecno
(imail-aSendOI "<ps«e55aggio
<
nwiato
?
-;?= 1cnecKed*"yes*-
Invio con
In
:
■'
7»
formato HTML «/td»
5uccesso!-:/p>";
} else { echo
'-:p>Errore:
" .S"ail-=ErrorInfo. "i/P»";
<ld«lnput
lype= "suonit"
nane-"Invia"
value-"In«ia me55aggto"</td>
</lr>
«/taBle»
<|..
mwmt-
foni per
la
composizione
de;
messaggi
imum
--=■
■cform method-"post1->
Smail->Host =
"mail.qualcosa.tld";
$mail->SHTPAuth = TRUE;
Se il server SHTP che vogliamo utilizzare è quello
//
de! nostro Internet provider, il parametro è lo stesso
Snail-iUsernsme =
'...';
utilizzato per la configurazione del nostro program
Smail->Password ■
'...';
indicazione nome
utente
e
password
ma di posta elettronica. Esso è costituito tipicamen te (ma non necessariamente) dal dominio di posta
Ogni messaggio che si rispetti, e questo vale non
elettronica prefissato da mail; ad esempio se il
solo per la posta elettronica ma in generale, oltre al
nostro indirizzo è nome@rjominio.tld, il server SMTP
destinatario ha un mittente ed un oggetto.
potrebbe essere mail. dominio .tld.
Cominciamo da questi ultimi, che impostiamo attra
Si presti attenzione al fatto che il server SMTP pre
verso le proprietà SFrom, SFromName e $Subject.
vede solitamente un'autenticazione attraverso
nome utente e password; in questo caso phpmailer
//
può effettuare l'autenticazione utilizzando le cre
Smail->From =
denziali che verranno fornite nel modo seguente:
//
e-mail del mittente
nome
'lou@latoserver.it":
completo del
$mail-»FronName = //
segnala che è
richiesta 1.'autenticazione
mittente
"Luca Balzerani";
// oggetto del messaggio
Come si evince dal frammento precedente, la spe
Srcail->Sub]ect = "Un caro saluto";
dizione del messaggio avviene invocando il metodo
SendO. il cui valore di ritorno (VERO o FALSO) ci Per quanto riguarda il destinatario, sappiamo che i
informa sulla buona riuscita della trasmissione. Se
messaggi di posta elettronica possono averne più di
qualcosa è andato storto possiamo visualizzare una
uno e, soprattutto, che possiamo avere diversi tipi
descrizione dell'errore verifìcatosi, accedendo alla
di destinatari:
proprietà SErrorlnfo. Fin qui abbiamo considerato la spedizione di un
> i destinatari diretti, i cui indirizzi sono specificati in campi To: (o A: );
messaggio testuale privo di allegati, un caso sem plice che ci ha permesso di iniziare a conoscere
> i destinatari per conoscenza, per cui si usano i campi Cc: {Carbon Copy, cioè copia conforme); > i destinatari nascosti, invisibili agli altri,
specificati con Bcc : (Blind Carbon Copy) o Ccn :
phpmailer. Ora siamo pronti per iniziare a fare sul serio.
Inserimento di allegati La possibilità di trasmettere file sotto forma di alle
(copia conforme nascosta)
gati a messaggi di posta elettronica è al contempo Con phpmailer abbiamo a disposizione un metodo
una comodità, per le infinite situazioni in cui torna
dì inserimento per ognuna di queste tipologie.
utile, ed una responsabilità, quella di non abusarne.
Supponendo, per iniziare, che il messaggio sia indi
Grazie a phpmailer possiamo aggiungere con sem
rizzato al direttore editoriale di questa rivista,
plicità degli allegati anche alle E-Mail inviate dalle
l'E-Mail del destinatario verrà impostata nel modo
nostre applicazioni in PHP. Dopo aver predisposto il
seguente:
messaggio, come mostrato in precedenza, l'inseri
$mail-=-AddAadress|'p.iassone@linuxpratico.conT ];
AddAttachment( ) e AdrJStringAttachmentt ).
Anche per i destinatari, come per il mittente, l'indi
file, prelevandolo da! filesystem, e prevede quattro
rizzo di posta elettronica può essere accompagnato
parametri, di cui solo il primo è obbligatorio:
mento di allegati avviene attraverso i metodi Il primo va utilizzato quando si vuole allegare un
dal nome completo, che va passato come secondo > il percorso del file da allegare;
argomento:
> il nome da attribuire al file (se se ne vuole Smail-=-AddAddress{ 'p. tassoneiaiinuxpratico.com1, 'Patrizio
specificare uno diverso dall'originale); Tassone'I ;
> il tipo di codifica da utilizzare {quella predefinita
è la cosiddetta base64); Invocando più volte il metodo AddAddress( ) potran
> il tipo MIME dell'allegato.
no essere aggiunti altri destinatari (sempre di tipo diretto). Supponiamo, ora, che lo stesso messaggio
Vediamo un esempio, supponendo che smail sia
debba essere inviato in copia {Cc) anche alla reda
un'istanza creata come spiegato nella prima parte
zione della rivista. L'istruzione da utilizzare sarà ia
dell'articolo.
seguente: //
allego
il
(ile
'allegato.pdi'
Smail-sAddCCI TedaiioniKaUnuxpratico.com');
Smail->AddAttachmerU( 'allegato.pdC );
Supponendo, infine, di voler specificare anche dei
Mediante tale istruzione alleghiamo al messaggio
destinatari in copia nascosta, cioè indirizzi a cui
che stiamo costruendo il file allegato.pdf situato
verrà recapitato il messaggio ma che non compari
nella directory corrente. Se avessimo voluto rinomi
ranno nell'elenco dei destinatari, ne indicheremo gli
nare il file, avremmo dovuto specificare il nuovo
indirizzi nel modo seguente:
nome come secondo argomento del metodo.
Smail->AdtìBCC( 'qualcunoiodoiiiinio. tld' ) ;
A questo punto non ci resta altro da fare che impo stare il testo del messaggio, che per il momento sarà solo testuale, e procedere alla spedizione.
RIQUADRO 2
Altre funzionalità Tra le funzionalità di phpmailer vogliamo segnalarne alcune, in ordine rigorosamente sparso, che possono rivelarsi estre
// testo del messaggio e-mail S^ail->Body =
"Testo
del
messaggio.*:
mamente utiìi. La proprietà SWordWrap permette di specifica re la lunghezza massima (in caratteri) di una riga; se viene specificato un valore, al momento della spedizione if testo del messaggio verrà modificato in modo che ogni riga vada a
//
spedizione del
ìf
(Smail->Send(>) echo
"Messaggio
messaggio
inviato!";
} else { echo
"Errore:
".Smail
capo entro tale limite.
E' possibile richiedere ricevute di avvenuta lettura del mes
{
>ErrorInfo;
saggio; a questo scopo è sufficiente indicare l'indirizzo a cui deve essere inviata tale ricevuta impostando la proprietà
SConf irmReadingTo. La proprietà SPrionty consente di impo stare il livello di priorità del messaggio ad un livello compre
so tra 1 (priorità minima) e 5 (priorità massima); il valore predefinito è 3.
(§0
// allego il file
Un messaggio HTML, come si è detto, può contene
'allegato.pdf'
// e lo rinomino in
re tutti gli elementi multimediali tipici di una pagina
'Relazione.pdf
$o!ail->AddAttachment( 'allegato.pdf',
"Relazione.pdf );
web. quali immagini, suoni, filmati e cosi via. Sebbene questi possano essere inclusi come allega
Può anche accadere, tuttavia, che i contenuti che
ti, solitamente viene utilizzato un metodo alternati
vogliamo creare non risiedano all'interno di file ma,
vo, che permette di incorporarli nella pagina. In tal
ad esempio, siano stati creati dinamicamente.
modo i file vengono mostrati come parte integrante
In queste circostanze possiamo creare al volo
del messaggio HTML. Per inserire allegati con que
l'allegato da inserire, utilizzando il metodo
sta modalità, phpmailer mette a disposizione il
AddStringAttachment(). Gli argomenti previsti da
metodo AddEmbeddedlmageO che prevede cinque
questo metodo sono analoghi a quelli descritti per
parametri:
AddAttachmentO, con due importanti differenze:
> il percorso del file da incorporare; > il primo argomento non è il percorso di un file
> l'identificativo CID (Content ID) con cui il file
ma la stringa il cui contenuto deve essere inviato come allegato;
verrà referenziato nel messaggio; > il nome da attribuire al file;
> il secondo argomento, il nome da attribuire all'allegato, diventa obbligatorio.
> la codifica; > il tipo MIME.
Vediamo un esempio.
L'unica peculiarità rispetto ai normali allegati è il
Sallegato = <«FINE
eventuali inconvenienti automobilistici), un identifi-
Questo è il contenuto dell'allegato.
cativo per mezzo del quale è possibile fare riferi
Solo due righe di testo.
mento all'allegato dal messaggio. In sostanza, il CID
FINE;
permette di indicare che si sta usando una risorsa
CIÒ (aerammo che non ha nulla a che fare con
incorporata. L'uso più classico di questa funzionalità $mail->AddStringAttachment(Sallegato,
'testo.txt');
è mostrato di seguito.
In questo modo la stringa $allegato verrà converti-
// un allegato "incorporato"
ta in un file denominato testo.txt e, come tale,
$mail->AddEmbeddedImage('logo.gif',
'logoazienda');
allegata al messaggio. //
riferimento all'allegato tramite il CID
$mail->Body = «<FINE;
Da diversi anni, ormai, i programmi di posta elettro
<p>Questo è il
nica consentono di comporre e visualizzare messag
<img src="cid:logoazienda"></p>
gi in formato HTML. Una E-Mail in HTML non è altro
FINE;
logo aziendale:<br>
che una pagina web: può contenere testo formatta to (con corsivo, grassetto, ecc), immagini, script e
Quando decidiamo di utilizzare il formato HTML per
così via. Se, da un lato, ciò consente di superare le
i nostri messaggi E-Mail, dobbiamo tenere a mente
limitazioni del formato testuale, dall'altro fa sorgere
che non tutti i programmi di posta sono in grado di
anche problemi di sicurezza (stante la possibilità di
visualizzarli. Per essere sicuri, quindi, che il messag
inserire componenti attive nel messaggio) ed indu
gio inviato risulti leggibile dal destinatario è oppor
ce, quindi, diffidenza in chi la riceve. L'uso di mes
tuno accompagnare sempre al testo in HTML l'equi
saggi HTML, di conseguenza, dovrebbe essere limi
valente versione testuale. Il client di posta
tato ai soli casi in cui se ne presenti la necessità.
elettronica, al momento dell'apertura del messag
Con phpmailer possiamo costruire E-Mail in formato
gio, selezionerà la versione appropriata. La versione
HTML procedendo in modo assolutamente analogo
testuale del messaggio deve essere assegnata alla
a quello già visto, con due sole differenze:
proprietà $AltBody.
> la proprietà $Body dovrà contenere il testo del
Smail->AltBody = "Versione testuale del messaggio";
messaggio in formato HTML anziché testuale; > dobbiamo segnalare a phpmailer che il
messaggio è in HTML, utilizzando il metodo Se abbiamo bisogno, per le nostre applicazioni PHP,
IsHTMLO.
di inviare messaggi di posta con allegati o in forma // contenuto HTML del messaggio
to HTML, phpmailer risulterà un notevole ausilio,
$mail->Body <«FINE
vista l'estrema semplicità con cui tali operazioni
<p>0uesto è un <i>messaggio e-mail</i>
possono essere compiute. Tanta semplicità, natural
in
formato <b>HTML</b>.</p>
mente, non dovrà indurre ad abusare di queste fun zionalità: anche nell'uso della posta elettronica non
FINE;
è inopportuno un richiamo al buon senso. Buon // segnala l'uso del
$mail->IsHTHL(true);
formato HTML
divertimento!
Costruirsi un blog in Php l weblog hanno ormai invaso la Rete, in questo articolo mostriamo
come costruirsi un proprio blog, installando e configurando uno degli applicativi più interessanti: Wordpress
Luca Balzerani <l.balzerani@linuxpratico.com>
II fenomeno dei weblog (o, ancor più brevemen te, blog) conosce da ormai diversi mesi un tale
crescendo di popolarità e diffusione da essersi guadagnato l'attenzione dei grande pubblico, oltre
PHP/MySQL e dotato di numerose caratteristiche
che degli "addetti ai lavori". Questa prorompente
interessanti. Nelle sezioni seguenti vedremo come
attualità è testimoniata, tra l'altro, dall'apertura di
installare e configurare Wordpress per realizzare un
blog sui siti web di moltissime testate editoriali, a
blog tutto nostro.
dimostrazione dell'interesse nutrito dal mondo dell'informazione verso quello che viene ritenuto un media promettente ed innovativo. Ma cos'è
Installazione dì Wordpress
effettivamente un blog?
Un blog è un sito web caratterizzato da una fre
Prima di installare Wordpress dobbiamo verificare
quenza di aggiornamento piuttosto elevata; sono
che siano soddisfatti alcuni requisiti.
esempi classici di blog le rubriche ospitate da quoti
E' necessario avere installato il server web Apache,
diani on-line e portali, i diari personali, le raccolte di
completo di supporto per il linguaggio PHP, ed il
link (solitamente tematiche) compilate da instanca
server di database MySQL. Nelle orincipali distribu
bili navigatori della Rete e così via. Gli elementi
zioni Linux la presenza di questi software potrà
costituenti ogni blog sono i messaggi (indicati spes
essere verificata utilizzando gli appositi applicativi
so con il termine inglese post) inviati da uno o più
per la gestione dei pacchetti; i medesimi applicativi
autori ed organizzati tipicamente in categorie.
consentiranno, in modo altrettanto semplice, di
La modalità di pubblicazione di tali messaggi rap
provvedere all'installazione di quelli eventualmente
presenta un'altra peculiarità dei blog, in quanto
mancanti. Assumiamo dunque la disponibilità del
essa è concepita in modo da risultare estremamen
software e passiamo alla fase successiva, la crea
te semplificata. Tutte le attività classiche di pubbli
zione del database.
cazione di contenuti sul web, che vanno dalla com
Per creare il database MySQL che verrà utilizzato da
posizione di pagine in formato HTML al loro
Wordpress sarà sufficiente aprire un terminale ed
trasferimento via FTP, vengono sostituite da mecca
eseguire il client mysql specificando l'opzione
nismi di pubblicazione istantanea. I blogger (così
■u
vengono chiamati gli autori di blog) possono com
l'account dì amministrazione.
root per indicare che vogliamo accedere con
porre i propri messaggi e pubblicarli immediata
mente grazie ad apposite interfacce: queste posso
$
mysql
-u
root
-p
no essere essenzialmente di due tipi:
RIQUADRO 1
> interfacce web - sostanzialmente analoghe a quelle di cui sono dotati i sistemi di gestione
contenuti, possono consistere di semplici caselle di testo o di più sofisticati editor visuali
Weblog, un po' di storia Un fenomeno interessante come quello dei blog non può non
implementati direttamente nel browser tramite
destare curiosità circa le sue origini. Mon dovrebbe essere
DHTML;
motivo di sorpresa, dunque, la presenza in Rete di numerose
> client XML-RPC - tradizionali applicazioni desktop
che consentono di comporre il messaggio e di trasmetterlo al blog utilizzando un opportuno protocollo basato su XML-RPC (in proposito sì veda il riquadro Blog e protocolli XML-RPC).
"storie ' dei weblog. Tra queste vogliamo segnalare al lettore la ricostruzione storica proposta da Dave Winer, personaggio
che può vantare, oltre alla paternità del formato XML-RPC, anche quella del blog più longevo, raggiungibile all'indirizzo: http://www.5criptingnews.com L'articolo contiene anche una piccola perla: il link ad una
copia di quello che fu il primo weblog in assoluto, cioè il sito
Un successo di pubblico ampio come quello ottenuto
http://info.cern.ch creato dall'inventore del World Wide
dai blog non poteva non determinare una prolifera
Web, Tim Berners-Lee. La storia dei weblog di Dave Winer è
zione di applicativi per la gestione di siti di questo tipo. In questo articolo ne presentiamo uno in parti colare, Wordpress, basato sul consueto abbinamento
disponibile all'indirizzo: http://newhome.weblogs.com/historyOfWeblogs
Dopo aver lanciato tale comando verrà richiesta la password dell'utente root; se non abbiamo modifi
- : :-.—r^~-
cato quella predefinita {la stringa vuota " ") sarà
J
sufficiente premere INVIO. La creazione vera e pro
;
WordPress
pria del database la effettueremo con il comando: mysql>
'■■■>'■'
create database wordpress:
Wdcome io WordPrras. We're now goins Mgothrougha fewsteps tog«yc up and runmng with th» laiest in personal pubbshmg platforrae. Btfore weg scarted, r'iriember that wertquirea PHP versionof al teast 4.1.0, you havt
Sarà bene provvedere anche alla creazione di un
4.3.O. LixV. good? You also n*«d te MC up thè database connection infcrmat in up-contiB.fhi>. Have you lookedatthe r^jJm^ì If you're ali ready, [
utente MySQL con privilegi minori rispetto all'utente root e. in particolare, ristretti alla sola gestione del
,.-) ■■:
database appena creato.
□
■■
Supponendo di voler creare un utente locale di
La pagina iniziale
nome luca e di attribuirgli la password pass. il
dell'installazione di Wordpress
comando da eseguire sarà il seguente: mysql> grant
ali
privileges
to
on
wordpress."
'lucaglocalhost'
identified
by
'pass'; ■
Ora che abbiamo creato tutti i presupposti per il buon funzionamento di Wordpress, possiamo proce
-
■,.•_,.
....
J
j j-V«.|
—>
dere con la relativa installazione. Dal sito web:
bitte O(*on dau irotrte-i oiray.
http://ijordpres5.org
Cto opt«n'lila insertai okay,
scarichiamo la versione più recente dell'applicativo,
OK. We^e nMrly 4iino now. W^ \ix: needto ut you a ceupl* of Ehings:
sotto forma di archivio ZIP. Nel nostro caso abbiamo
prelevato la versione 1.2, identificata dal nome in codice Mingus e contenuta ne! file wordpress-1.2mingus . zip. Ci spostiamo, poi, all'indirizzo:
" "J
Cj:r::r. i^"i:r.>;r'vì :^r■!'.■.
Whal is rhe w^b addrec Df ycur WardFress instalktìon? (We prottìbly
. iiased 11 fcr you eotTectly.) fi
- -
C11 li
SHf 1
■>Lifl(w(((/
http://wiki.wordpress.org/WordPressLocalization
per scaricare il file binario it IT.mo, contenente la
La creazione del database
localizzazione italiana di Wordpress. Completato il
è andata a buon fine
download, da una finestra di terminale decompri miamo il file ZIP con il comando seguente:
i
unzip wordpress-1.2-mingu5.2ip
Verrà così creata una cartella di nome wordpress contenente tutti i file della distribuzione. Per
aggiungere il supporto alla lingua italiana dobbiamo copiare il file it IT.mo, scaricato in precedenza, in una cartella di nome languages che dovremo creare all'interno di wordpress/wp-includes.
%
mkdi r
ì cp
wordpress/wp-ineludea/languages
it IT.uo wordpress/wp-includes/languages/
11 passo successivo è la configurazione dell'accesso al database MySQL. Nella cartella wordpress trovia mo un esempio di file di configurazione denominato
wp-conf ig-sample. php: dobbiamo copiarlo in un nuovo file che chiameremo wp-conf ig. php e che
Ecco come sì presenta
andremo a modificare (utilizzando un qualsiasi
nostro blog al primo accesso
editor testuale) per specificare i parametri per la connessione. Le operazioni appena descritte posso no essere effettuate nel modo seguente:
$
ed
definel'DB NAME1,
'wordpress'];
$
cp wp-config-sample.prip wp-confìy.php
definel'DB USER1,
'username'];
$
kwrite
defineCDB PASSWORD1,
wordpress/
wp-config.php
&
definel'OB HOST1,
password');
'localhost');
Nella parte iniziale del file wp-config.php trovere mo alcune righe simili alle seguenti:
La prima istruzione define crea la costante DB NAME
e le assegna il nome del database MySQL che verrà //
•*
M/5QL
settings
"
//
utilizzato da Wordpress; nel nostro caso abbiamo
deciso di chiamarlo proprio wordpress per cui non
comando seguente:
abbiamo bisogno di apportare modifiche. La secon da e la terza istruzione, invece, devono essere
S
cp
-R wordpress
/var/www/html/
modificate: il valore della costante DB USER dovrà essere quello dell'utente MySQL che abbiamo crea
In questo modo la nostra installazione di Wordpress
to (cioè luca), mentre DB PASSWORD dovrà contene
sarà accessibile come:
re la corrispondente password di accesso (pass nel
http://localhost/wordpress/
nostro caso}.
Ai primo accesso deve essere richiamata la pagina
Spostandoci poche righe più in basso, troviamo la
/wp-admin/install.php che, attraverso una proce
definizione della costante WPLANG, che imposta la
dura guidata, si occuperà di completare l'installa
lingua dell'interfaccia (quella predefinita è, ovvia
zione di Wordpress. Se abbiamo copiato i file nel
mente, l'inglese):
modo esemplificato sopra, il percorso completo a cui accedere sarà il seguente:
define
('wplang1,
http://localhost/wordpre5s/wp-admin/instaU.php
" );
Si presti attenzione al fatto che al termine della
Affinchè Wordpress utilizzi la traduzione italiana
suddetta procedura guidata verrà mostrata una
dobbiamo modificare tale istruzione come segue:
password. generata in modo casuale, che servirà
define
stratore del blog): è bene annotarla. Subito dopo,
per il primo accesso dell'utente admin (l'ammini cwpung1 ,
u
ir );
infatti, verremo condotti automaticamente alla Terminata la fase di configurazione, non ci resta altro
pagina di autenticazione:
da fare che copiare l'intera directory wordpress
http://local.host/wordpress/v4j-login.php
nella posizione desiderata all'interno delle cartelle
in cui dovremo inserire il nome utente dell'ammini
accessibili via web. Ad esempio, se la cartella base
stratore (admin) e la password annotata in prece
(la web root) è /var/www/html, potremo usare il
denza. In questo modo avremo accesso al pannello di amministrazione del blog.
Configurazione di
Wordpress WordPress Opil
ni
i:i
pi
I«n*M
ftofllc
tate.
II pannello di amministrazione da accesso a tutte le ■
operazioni di gestione del blog: ogni aspetto del funzionamento di Wordpress viene controllato da
1 J]l7li>lll "ellrull
qui. L'interfaccia utente del pannello è piuttosto putita ed elegante: un menu orizzontale, posto in ■il :- --
-.;
-;-■-■
cima alla
pagina,
permette di accedere rapida
mente alle diverse funzionalità.
Al primo accesso è consigliabile iniziare il proprio
indlriKO<io]blop(l"Rn
tour in Wordpress dal menu Profilo, ne! quale IndlittroC iTiail
andremo a completare le informazioni sul nostro account di amministrazione: nome e cognome, una
breve presentazione, il nomignolo (0 nickname) con La scelta delle opzioni generali durante la configurazione di Wordpress
il quale firmare i nostri post, l'indirizzo E-Mail e le eventuali coordinate per i'instant messaging. Da
questa pagina abbiamo anche la possibilità di modi ficare la password di accesso, che vorremo proba
RIQUADRO 2
Pubblicazione via E-Mail
bilmente sostituire con una meno bizzarra (e più mnemonica) di quella generata per noi dal sistema.
Premendo il tasto Aggiorna profilo, situato in fondo alla pagina, le modifiche apportate verranno memorizzate.
Oltre all'interfaccia web ed al supporto ai client XML-RPC,
Wordpress mette a disposizione anche un altro interessante metodo per la pubblicazione di articoli: la posta elettronica. E' possibile, infatti, indicare i parametri di un accounl POP3
Passiamo poi a personalizzare il funzionamento del blog attraverso il menu Opzioni. Le opzioni generali (prima voce del menu secondario) ci consentono di
(indirizzo del server, nome utente e password) al quale i
indicare il titolo del blog ed una sua brevissima
post saranno inviati come normali messaggi di posta elet
descrizione (denominata tagline). Seguono gli URL
tronica. Successivamente sarà sufficiente invocare lo script
relativi all'installazione di Wordpress ed all'indirizzo
http://localhost/wordpress/wp-mail.php
principale del blog e l'indirizzo E-Mail dell'ammini
per trasformare i messaggi ricevuti in articoli del blog. Programmando una esecuzione periodica di tale script (uti lizzando il demone crond o qualsiasi altro software che ci
stratore. Le due caselle di spunta seguenti, identifi
cate dalia voce Appartenenza, hanno un impatto
consenta di richiamare a determinati intervalli la URL
determinante sulle modalità di funzionamento del
sopraindicata) otterremo un riversamento automatico dalla
blog.
mailbox al blog.
La prima opzione, se attivata (come è nella configu razione predefinita), fa sì che qualunque visitatore
35
comunità di utenti del blog debba essere a parte
cipazione spontanea (chiunque può aderirvi) o regolamentata.
La seconda opzione, inizialmente disattivata, stabi
[WordPress Scrivi
ModifKa
CaMfcrn
Lnlr
urim
.
). -1 1
'-
'i
lisce se qualunque utente registrato possa pubbli
V. -jdcSii
care articoli; va dunque utilizzata con prudenza. ^|««t>l
II mu» primo ";i*f" ...
■
' ■
L
-■
.
f
Iffig
ul
d
h
ocpie
foonfl
(J(t
DicL
Il successivo riquadro (data e ora) contiene le impo stazioni relative al fuso orario (espresso come diffe renza rispetto all'ora di Greenwich), al formato delle
**" -;ltlBtoWn
■"
date e dell'ora; per questi ultimi si consigliano i for mati d/m/Y e H:i, rispettivamente. Il secondo sotto menu. Scrivere, da accesso alle opzioni relative all'ambiente di scrittura dei post (le varie imposta zioni dovrebbero risultare autoesplicative), alle noti-
Miali m Ti.-llwl,. '
1
fiche automatiche {si consiglia di cancellare il con
r. .,,:•
tenuto della casella Aggiorna servizi), ed alla M^-"-
■
■
-
-
Ecco cosa compare selezionando il menu Scrivi: il form per la composizione dei nostri post
funzionalità di pubblicazione via E-Mail. il sottomenu Leggere permette di specificare quanti messaggi visualizzare sulla pagina principale, consentendo di scegliere tra gli n post più recenti e quelli degli ulti
"
mi n giorni; nel riquadro seguente viene specificato il numero di messaggi da pubblicare, in modo sinteti
RIQUADRO 3
co o integrale, nel flusso RSS (si veda il riquadro 3). La successiva voce di menu (Discussione) conduce alle impostazioni predefinite per i messaggi pubbli
I formati RSS
cati, alle eventuali notifiche via E-Mail da inviare in
L'acronimo RSS. caratterizzato da molteplici interpretazìoni
caso di inserimento, approvazione o cancellazione
(di cui la prevalente è Really Simple Syndication), indica un
di commenti, e soprattutto alle modalità di modera
formato XML per la pubblicazione di flussi di notizie (feed).
zione di questi ultimi. Si possono richiedere, in par
Denominatore comune delle numerose varianti esistenti di
RSS è la possibilità di elaborare in modo automatico tali feed. consentendo di condividere ed aggregare flussi informativi provenienti da fonti diverse.
ticolare, la preventiva approvazione di un ammini
stratore o l'inserimento, da parte dell'autore, di nome ed indirizzo di posta elettronica. Le ultime
due opzioni forniscono delle euristiche, basate sul numero di link o sulla presenza di determinate
RIQUADRO 4
li progetto Wordpress
parole all'interno del commento, per cercare di con trastare lo spamming.
Terminata questa panoramica sulle impostazioni più importanti della configurazione di Wordpress, lasciamo al lettore interessato la scoperta di tutte le
La crescente diffusione dei webiog ha provocato un'autentica
altre (sono ancora numerose), rinviando a questo
esplosione di applicativi, sia OpenSource che commerciali,
scopo alla documentazione ufficiale o al wiki di sup
per la realizzazione di questa particolare tipologia di siti. L'offerta, in questo senso, spazia dai moduli per i principali sistemi di gestione contenuti fino ad applicazioni ad hoc. Il
porto (si veda il riquadro 4 sul progetto Wordpress). Dopo tanto indaffararsi per installare e configurare
"blog engme" presentato in questo articolo è Wordpress,
Wordpress, siamo pronti per pubblicare il nostro
un'applicativo sviluppato nel familiare contesto LAMP (Linux
primo post, operazione talmente semplice ed intui
+ Apache + MySQL + PHP) e rilasciato con licenza GPL.
tiva da non richiedere spiegazioni aggiuntive o rac
il sito ufficiale di Wordpress. da cui è possibile scaricare la
comandazioni, se non quella di utilizzare la funzione
versione più aggiornata del software ed accedere ad altre
risorse (documentazione, forum, testimonianze, ecc.) è: http://vzordpress.org
Tra i link di maggiore interesse segnaliamo in particolare i seguenti: La documentazione ufficiale di Wordpress: http://wordpress.org/docs/ II Wiki di supporto: http://wiki.wordpress.org/ II canale IRC (Internet Relay Chat) dedicato a Wordpress: http://wiki.wordpress.org/index.php/IRC
di Logout al termine della sessione di lavoro.
Benvenuti nel mondo dei webiog.
Conclusioni Tra i numerosi applicativi per la gestione di webiog, Wordpress sì contraddistingue per le numerose e sofisticate funzionalità. In questo articolo, dopo aver introdotto la particola
re tipologia di siti web denominati blog, abbiamo mostrato come installare Wordpress ed abbiamo
fornito le indicazioni fondamentali per la sua confi gurazione.
Recita il proverbio: "Se son rose fioriranno", e non
del blog possa registrare un proprio profilo.
abbiamo dubbi che il lettore interessato a crearsi un
Disattivandola, al contrario, si stabilisce che solo gli
proprio blog a questo punto della lettura avrà già
amministratori del blog possano registrare degli
pubblicato il suo primo post.
utenti. In pratica tale opzione specifica se la
Ofe
-
Generare file Excel -Kls con PHP Vediamo passo passo come sia posibile ottenere la generazione di fogli di calcolo Excel tramite l'utilizzo di PHP, utili sia per la generazione di report che di tabelle formattate.
Luca BaUerani <l.balzerani@linuxpratico.com>
Una applicazione web sviluppata in PHP rap presenta molto spesso un'interfaccia attra
verso la quale è possibile operare su una base di dati. In uno scenario di questo tipo, quindi,
quale potremo generare i tanto agognati fogli di
è possibile individuare due livelli distinti: il livello
calcolo in formato Excel.
dei dati, cioè il database, e quello dell'applicazione
Vale la pena di precisare, per anticipare una proba
(spesso denominato livello di business togic). Grazie
bile curiosità del lettore, che la libreria che ci accin
alla separazione tra i due livelli gii utenti possono
giamo ad utilizzare permette solamente {si fa per
lavorare sulla base di dati attraverso una opportuna
dire) di creare file Excel e non anche di aprirli o
interfaccia (composta di pagine, maschere, pulsanti
modificarli. Di conseguenza essa ci consente di
e così via) invece che manipolandola direttamente,
implementare esclusivamente funzionalità di espor
ottenendo così l'importante risultato di nasconder
tazione di dati in tale formato.
ne la complessità.
Non ci resta altro da fare, a questo punto, se non
Non è infrequente, tuttavia, che ad un certo punto
procedere con l'installazione di PEAR, che illustrere
si ponga la necessità di esportare i dati per condivi
mo assumendo di avere a disposizione un'installa
derli con altri utenti o elaborarli su sistemi diversi.
zione funzionante di PHP.
In circostanze del genere diventa necessario, allora, individuare il modo più opportuno per rappresenta
Installazione di PEHR
re i dati estrapolati così da facilitarne lo scambio.
Se
Se la quantità di dati da trasferire non è eccessiva,
computer è
la
versione
di
PHP
installata
una eccellente soluzione può essere quella di utiliz
successive), abbiamo già a disposizione localmente
zare un foglio elettronico, adottando un formato che
go-pear.php, lo script necessario per avviare l'in
possa essere facilmente gestito da qualsiasi utente,
stallazione di PEAR. Se, al contrario, abbiamo una
compresi coloro che non lavorano in ambiente
versione precedente di PHP, possiamo ottenenerne
sufficientemente
sul
nostro
recente (4.3.x
o
Linux. Per questo motivo, nel presente articolo
una versione aggiornata accedendo all'indirizzo:
mostreremo come sia possibile utilizzare PHP per
http://go-pear.org
generare fogli elettronici in formato Excel, ì quali
e salvando la pagina risultante in un file che
potranno essere aperti senza difficoltà sia con
RIQUADRO 1
Microsoft Excel che con Cale, il foglio elettronico della suite OpenOffice.org.
li tempo delle pere Per generare i nostri fogli Excel utilizzeremo un package PEAR, cioè un pacchetto appartenente ad
PEAR PEAR è una libreria strutturata di codice PHP, scritto secondo
precise convenzioni in modo da essere quanto più possibile uniforme anche stilisticamente. Il nome PEAR è un acronimo
un repertorio standard di estensioni per PHP. deno
per "PHP Extension and Application Repository" [repertorio di
minato per l'appunto PEAR (PHP Extension ano
applicazioni ed estensioni PHP). Lo scopo di PEAR è quello di
Application Repository). La "filosofia" di PEAR è
mettere a disposizione dei programmatori PHP una vasta rac
quella di mettere a disposizione dei programmatori PHP una vasta libreria di codice riusabile di elevata
colta di codice pronto per l'uso e rilasciato rigorosamente sotto licenza Open5ource.
Le librerie che compongono PEAR. denominate packages.
qualità, analogamente a quanto avviene con CPAN
coprono una vastissima gamma di necessità di programmazio
nei caso del linguaggio Peri o CTAN nel caso di
ne; solo per citare alcuni esempi si parte da quelle più comuni (accesso standardizzato a numerosi DBMS, manipolazione di
TeX/LaTeX.
PEAR comprende librerie che coprono una vastissi
ma gamma di esigenze: dalla connessione a data base (attraverso un sofisticato abstraction layer)
documenti testuali, in HTML e XML, logging) a quelle apparen temente più esotiche (come nel caso della sene di Fitionacci), dalle più concrete (sistemi di pagamento, autenticazione) fino alle più concettuali (manipolazione di strutture dati, tecnologie
alla manipolazione di documenti HTML e XML,
per il web semantico). Il sito di riferimento del progetto è:
dall'autenticazione ai principali servizi di rete e
http://pear.php.net
molto altro ancora [riquadro 1).
mentre la lista aggiornata dei pacchetti disponibili si trova qui:
In questa sede, comunque, ci limiteremo a conside
http://pear.php.net/packages.php
rare il package Spreadsheet
Excel Writer con il
LISTATO 1
m
(
^^H
fé?\ Un generatore di ...
Schema per la
^Ur tabellone
creazione di file Excel
<?php
<?php
//
Inclusione del package PEAR per la
// di
require once
creazione
foglio di
Se voglio creare un
Sworkbook =
calcolo
—
//
new Spreadsheet Excel_Writer( 'nomef ile.xls' ) ;
file Excel deve essere inviato al
Intestazioni di
il seguente metodo invia
// Creazione di
//
un
foglio di
Sworksheet
Si«19;
ti++)
lavoro I"worksheel"}
Calcolo dei
for ($1-1;
di uno)
for
=£. Sworkbook->addWorksheet('Fogliol');
{ Si):
6,
Si);
Si*-*)
Sj<=16;
{
$J*+)
Sworksheet-swrite(Si, //
operazioni
//
II
sui
file Excel
colonna
prodotti
Si<-18;
t$J-l;
di
$i,
Sworksheet->writelSi,
le opportune intestazioni HTTP }
(possono essere più'
(Si«l;
riga e
Sworksheet ^writeie.
browser
Swo r kbook-ssendC nomef i le. xls' );
//
=& Sworkbook->addMorksheeti 'Tabelline');
Sworksheet
("workbook")
file devo inflicarne il nome
for // Se il
new Spreadsheet ExcelWrit erCtabetline.xls');
Sworkbook =
'Spreadsheet/Excel/Writer.php';
// Creazione di una
//
'Spreadsheet/Excel/Writer .php';
fogli di calcolo in formato Excel
require once
//
LISTATO 2
{ Sj,
Si'Sj)
dati...
è
pronto:
passo
generarlo Sworkbook->close();
Sworkbook->close{);
?>
V
chiameremo per l'appunto go-pear.php. Ora dob
-
Salvando il listato precedente in un file di nome
biamo attivare la connessione ad Internet ed ese
hello.php, lo script può essere eseguito da riga di
guire tale script da riga di comando:
comando posizionandosi nella cartella in cui si trova
i
seguente:
il file ed invocando l'interprete PHP nel modo php go-pear.php
Si avvierà così la procedura guidata di installazione
S
php
hello.php
del package manager, il gestore di pacchetti di PEAR. Al termine di tale procedura sarà possibile
Se tutto è andato secondo i piani nella cartella cor
invocare quest'ultimo, con il comando pear. per
rente
installare il software necessario per il nostro artico
hello.xls analogo a quello mostrato in figura 1.
lo. I comandi da eseguire saranno i seguenti:
Analizziamo ora nel dettaglio il significato delle
dovrebbe
essere
stato
creato
un
file
righe del listato di esempio. S pear instali OLE S pear
instali
Spreadsheet Excel Wrlter
ILa prima istruzione si occupa di includere la
classe principale del package; se nel file di con
Arriva "Hello, worid! '
figurazione di PHP (il ben noto php. ini) la direttiva
include path è stata impostata in modo da conte
Completata l'installazione dei pacchetti necessari,
nere anche il percorso in cui si trova PEAR, non ci
possiamo finalmente metterci all'opera. Iniziamo
sarà bisogno in nessun caso di modificare il percor
con un esempio che, pur nella sua estrema banali
so mostrato.
tà, ci consente di verificare la correttezza dell'instal lazione e di fornire uno schema generale per l'uso del package Spreadsheet
Excel Writer. Il sorgen
te di questo primo esempio è riportato di seguito.
2 Con la seconda istruzione viene creata un'istan
za della classe Spreadsheet Excel/Writer; tale oggetto rappresenta ti foglio elettronico che stiamo
creando: oltre a contenerne i dati, fornisce i metodi che ci permettono di operare su di esso. Il costrut
<?php
require once
'Spreadsheet/Excel/Wrlter.php";
tore della classe ha un parametro opzionale. Se il nostro scopo è quello di creare un file sul disco rigi
Sworkbook = Sworksheet
new Spreatfsheet =(.
Excel Writerf'hello.xls');
Sworkbook->addWorksheet ( ' Fogliol' ] ;
Sworksheet->write(G,
$workbook->close();
0,
Hello,
world?');
do (come avviene, tipicamente, nell'uso di PHP a riga di comando) dobbiamo utilizzare tale parame tro per indicare il nome del file da creare, come mostrato nell'esempio. Il parametro va omesso,
invece,
se
il
foglio
elettronico
che
stiamo
generando deve essere inviato ad un browser; in
5Una volta terminata la predisposizione del
questo caso sull'istanza creata deve essere invoca
foglio elettronico deve essere invocato il meto
to il metodo send(), al quale andrà fornito come
do close{), il quale provvedere a generare la rap
argomento il nome del file.
presentazione binaria del file e subito dopo a
memorizzarlo o inviarlo al browser.
311 passo successivo è la creazione di un foglio di
La sequenza dei passi da eseguire viene riepilogata
lavoro (o worksheet); ogni foglio elettronico può
nello schema generale mostrato nel listato 1. A
contenere uno o più fogli di lavoro, selezionatali
questo punto possiamo iniziare ad occuparci di fogli
attraverso le apposite "linguette" di Excel o Cale. La
di calcolo più sofisticati, ma non prima di aver spie
creazione di un foglio di lavoro viene effettuata
gato il funzionamento del sistema di coordinate.
mediante il metodo addWorksheet ( ), a cui deve
Coordinate
essere passato come parametro il nome da asse gnare al foglio. Si noti l'uso dell'operatore di asse
In un foglio di calcolo, ogni cella è individuata uni
gnamento =&, essenziale per far sì che la variabile
vocamente da una coppia di coordinate, costituite
$worksheet punti all'oggetto appropriato.
rispettivamente da una lettera (usualmente scritta
4Effettuata la creazione di un foglio di calcolo e
colonna (A corrisponde alla prima, B a quella imme
in maiuscolo) e da un numero: la prima specifica la
l'inserimento di almeno un foglio di lavoro si
diatamente a destra e così via) mentre la seconda
passa alla gestione del contenuto. Si tratta della
corrisponde al numero di riga (dall'alto verso il
fase più importante, durante la quale vengono inse
basso). Questo modo di specificare !e coordinate di
riti valori e formule nelle celle del foglio elettronico
una cella viene chiamato formato Al. Abbiamo
e viene applicata la formattazione. Nell'esempio
visto dall'esempio precedente, tuttavia, che nel
mostrato ci si è limitati ad inserire nella prima cella
codice PHP le coordinate vengono specificate
del foglio di calcolo la stringa Hello, world!.
numericamente:
Swork5heet->urite(6,
0,
'Hello,
world!');
RIQUADRO 2 II metodo writeO prevede tre argomenti: il primo
Excel Vs. Cale
corrisponde alia coordinata di riga (lo zero corri
sponde ad A, uno corrisponde a B e così via), il I due principali software per la gestione di fogli elettronici
secondo alla coordinata di colonna (lo zero corri
presenti sul mercato, Microsoft Excel e OpenOffice.org Cale,
sponde alla prima colonna) mentre il terzo argo
presentano numerose analogie ma anche differenze più o
mento è il valore da assegnare alla cella cosi indivi
meno rilevanti. Tra queste ne va segnalata una che può cau
duata. Dal punto di vista del programmatore è
sare un iniziale disorientamento nell'utente: la terminologia. Nel gergo di Excel, infatti, un file viene chiamato cartella di
sicuramente più pratico referenziare le celle del
lavoro (traduzione del termine inglese workbook) mentre i
foglio di calcolo servendosi di coordinate numeri
singoli fogli elettronici al suo interno sono denominati fogli di
che. In alcune situazioni, tuttavia, è necessario tra
lavoro (da worksheet).
durre taii coordinate nel formato Al. A questo
Nel caso di OpenOffice.org Caie, invece, i termini utilizzati
scopo la classe Spreadsheet
sono rispettivamente foglio elettronico e tabella.
Excel Writer mette a
disposizione il metodo rowcolToCell ( ) che, data una coordinata numerica, restituisce il corrispon dente formato Al.
lì B
A
1
//
! Hello, «orlo!
Hello, worid!
1
C
|
Questa
istruzione
stampa
"E3"
echo Sworkbook->rowcolToCell(2.
D
4) ;
z
Si noti che il metodo può essere invocato anche
3
staticamente, cioè al di fuori di un contesto di istan
A
za, utilizzando la usuale sintassi: "Hello, world"... in Excel! //
Invocazione
statica del
metodo
echo Spreadsheet Excel Writer: : rowcolToCeU|2,
4);
Per esercitarci sull'uso delle coordinate consideria e
1 ,
1
fi
2 2
3
1
i
T
2 3
4
■_
3 4
4
e
12
•
5
5
■■■
7
■
i
-.
-t
■
7
7
14
21
a 9
16
14
9
18
IO
10
27 30
\
© 1
i
1
1
a IO 11
;
9 -■
4
5
E
5
E
e 12
15
18
16 30
30 25
74
2* 23 32
X
30 3E
---
42
■■■" 45 SO
ED
36 W
-
|
T
; ■ i
-
Calcolo delle tabelline direttamente nel
foglio elettronico
J
mo un classico dell'aritmetica:
le tabelline.
Vogliamo scrivere, cioè, un'applicazione PHP che generi un file con le tabelline dall'I al 10: sulla
prima riga e sulla prima colonna avremo i numeri da 1 a 10 mentre in corrispondenza di ogni incrocio avremo il relativo prodotto. II sorgente dell'esercizio è riportato nel listato 2, mentre una porzione del foglio di calcolo risultante è mostrata in figura 2,
discusso ifcrecedenza; in alternativa è possibile
LISTATO 3
applicare ■formato ad un'intera riga utilizzando
metodoBtRow().
Utilizza di formule
A titolo di
ipio consideriamo il seguente fram-
mento di co< require once Sworkbook
=
'Spreadsheet/Excel/Writer.php'; new Spreadsheet
Excel_Writer('forrajle.xls'
sworksheet -l, Sworkbook->addWorksheet('Uso di
formule'
Sffiiint =& Swfctiook->addFormat{);
Sfra_int->setFoBFamily( 'Helvetica- ) ; $fm_int->setAlBnC center1 );
Scentrato
=&
SworkboQk->addFormaT():
Scentrato*>setAligri|'center'); Scentrato-*setBoia() ;
Sintest = array("a", Svalorì « array(2,
La prima istruzione crea, all'interno del foglio di cal "b",
3,
"a*\>".
"-A2+B2",
"a*b"); -=A2*B2");
Sworksheet->writeRow(Q,
Q,
Sintesi,
Scentrato!;
Sworksheet->writeRow(1,
G,
Svalori,
Scentrato);
colo Sworkbook, un nuovo formato al quale associa
mo la variabile $fm int. Nella riga seguente viene utilizzato il metodo setFontFamily{} per impostare il font desiderato (in questo caso abbiamo scelto Helvetica per motivi di portabilità). La terza istruzio ne usa il metodo setAlignO per specificare che il contenuto delle celle a cui viene applicato tale for
-
mato deve essere allineato al centro.
L'ultima riga, infine, imposta lo stile grassetto. Una versione modificata del nostro generatore di tabelline, che fa uso di formati, potete scaricarla da http://v**/. linuxpratico.com/risorse/sviluppo/
Formule La caratteristica principale dei fogli di calcolo, quel
la che per intenderci ne ha decretato il grande suc cesso, è la possibilità di eseguire in modo automati co dei calcoli, che si tratti di semplici somme o di formule arbitrariamente complesse. Molto spesso, Utilizzo di formule all'interno di Excel direttamente da PHP
del resto, i fogli di calcolo vengono utilizzati per implementare dei semplicissimi programmi in cui l'input corrisponde ai valori immessi dall'utente in
apposite caselle e l'output è il risuftato della valutazione di formule. Per nostra fortuna, l'inserimento di
Utilizzo di formati
formule nel foglio Excel che stiamo generando non pone problemi di sorta. Sarà sufficiente, infatti, uti
II foglio di calcolo appena creato assolve certamen
lizzare l'apposito metodo writeFormu\a( ) in luogo
te la propria funzione ma risulta piuttosto sgradevo
del semplice writet) usato in precedenza, come
le sul piano estetico. Sarebbe decisamente più pia
mostrato di seguito.
~
cevole e leggibile se, ad esempio, le colonne fossero più strette, i numeri centrati e le intestazio
//
ni evidenziate in grassetto. Vediamo allora come
Sworksheet-*write(O,
applicare la formattazione alle nostre celle.
// Calcolo il suo doppio
Si tratta di un procedimento articolato in tre passi:
Sworksheet->writeFormula(8,
o il primo passo è la creazione di un formato
scrivo
"5" nella cella Al G,
"5");
1,
'=A1'2"
Nelle formula è possibile fare uso anche delle fun
mediante il metodo addFormatf ) della classe
zioni native di Excel, come SUM o PRODUCT.
Spreadsheet Excel_Writer; si presti attenzione
Come si vede facilmente dall'esempio, la sintassi
al fatto che il formato viene associato al foglio di
utilizzata da Excel (e da Cale) per la scrittura di for
lavoro corrente e non è utilizzabile al di fuori di
mule fa uso del formato Al
esso;
Quando la struttura del file che si sta generando
o il secondo passo consiste nella definizione del
per le coordinate.
non è nota a priori, quindi, sarà necessario utilizza
formato, cioè nello specificare, attraverso i
re la già citata funzione rowcolToCell ( )
metodi della classe
vertire opportunamente le coordinate numeriche.
SpreadsheetExcel WriterFormat, le caratteristiche del formato: il tipo di carattere, gli eventuali stili grassetto e corsivo, etc; o l'ultima operazione è l'applicazione del formato
per con-
Conclusioni Generare fogli elettronici in formato Excel non è solo possibile ma anche semplice e divertente.
ad una cella o ad un insieme di celle. Il formato
Al lettore ora il compito di scoprire quante esigenze
da applicare ad una singola cella viene fornito
potrà soddisfare avendo a disposizione questa ulte
come quarto argomento del metodo writel )
riore risorsa. Buon calcolo.