LinuxPratico - Sviluppo Web

Page 1

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

:

■'

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.


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.