Laboratorio di Sistemi Informativi
Validazione dei dati
Veniamo ad una problematica
tipica delle applicazioni sulle basi di dati: la validazione dei dati
inseriti. Si tratta di fare in modo che le operazioni richieste
dall'utente non violino i vincoli di integrità imposti sulla
base di dati. Ad esempio, nel caso della procedura di inserimento di
nuovi voli, sarebbe preferibile che il sistema si rifiutasse di
inserire un volo quando o il codice o il codice aeroporto
partenza/destinazione non corrisponda ad un dato effettivamentre
presente nel database (è un cosidetto "vincolo di chiave esterna")
Ci sono tre possibili ambienti in cui effettuare la validazione dei
dati in una
architettura a tre livelli:
- nel server database
- nel server applicativo (il server web nel nostro caso)
- nel client (il browser)
La validazione all'interno del browser fa sì che i dati non
vengano neanche spediti al server web. Ad esempio, se l'utente immette
una stringa dove il sistema si aspetta un numero, è possibile
far sì che il browser si accorga di questo fatto e richieda
all'utente di reimmettere i dati. La validazione lato client richiede
l'utilizzo del linguaggio Javascript.
Notare che la validazione lato client non è sicura!! L'utente
può sempre disattivare Javascript e quindi aggirare (volente o
nolente) i controlli.
Quando la validazione dati è eseguita sul server web, il
programma che gestisce l'applicazione (i vari script PHP nel nostro
caso) effettuano dei controlli prima di effetturare eventuali modifiche
nella base di dati. La modifica viene effettuata solo se il controllo
ha successo, altrimenti si visualizza un appropriato messaggio di
errore.
Infine, si può relegare tutto al DBMS: questo può
controllare la validità dei vincoli di chiavi esterna, o anche
vincoli più complessi qualora questi siano supportati.
Tuttavia un approccio di questo tipo è poco
efficiente (i dati devono viaggiare dal client fino al server DBMS
anche quando errati). Inoltre, è necessario comunque che
l'errore venga mostrato all'utente, per cui comunque lo script PHP deve
riconoscere che si è verificato un errore nell'esecuzione di un
comando SQL, capire a cosa è dovuto questo errore, e
visualizzare il messaggio appropriato. Se a ciò aggiungiamo che
MySQL offre solo un supporto limitato al trattamento dei vincoli di
integrità, si capisce che questo è un approccio che
è meglio lasciar perdere.
Modelli di validazione
Decidere come visualizzare i messaggi di errori dovuti alla presenza di
dati sbagliati è un problema difficile. Se questo aspetto
dell'applicazione viene pensato male, l'utente può trovarsi
infastidito da continui messaggi di errori, difficili da eliminare,
magari anche inaccurati o poco informativi. Non c'è niente di
peggio che avere un messaggio che dice che si è verificato un
errore ma non spiega in che campo di input c'è il problema.
La validazione è in
realtà un processo composto da due fasi: trovare gli errori e presentarli all'utente. La
ricerca degli errori può essere:
- interattiva, quando gli
errori vengono controllati mano a mano che l'utente immette i dati;
- a posteriori, quando gli
errori sono controllati quando l'utente ha finito di immettere tutti i
dati.
Notare che la validazione interattiva è praticabile solo lato
client. Se si volesse realizzare lato server, sarebbe necessario
inviare i dati al server web ogni volta che l'utente modifica un campo
di una form, causando una perdita di tempo inaccettabile.
Gli errori possono essere presentati all'utente in due modi:
- un campo alla volta,
se un nuovo messaggio è mostrato all'utente per ogni errore
trovato;
- in maniera batch,
quando tutti gli errori sono presentati con un messaggio unico.
Come per il caso precedente, quando la validazione è lato server
la presentazione batch degli errori è preferibile, perché
più efficiente. Visualizzare gli errori uno alla volta, chiedere
di correggerli, e passare poi all'errore successivo richiede continui
passaggi di dati tra browser e server web che renderebbero il tutto
troppo lento.
In generale la soluzione migliore è avere una validazione batch
a posteriori sul lato server assieme ad una validazione lato client
(che può essere di qualunque tipo si desideri). Perché
raddoppiare le validazioni?
- la validazione lato server è essenziale perchè non
può essere aggirata dall'utente. In questo modo ci si assicura
veramente che i dati inseriti rispettino tutti i vincoli richiesti.
- la validazione lato client è però più
efficiente, e inoltre può essere sia eseguita a posteriori che
interattiva, adattandosi quindi meglio al tipo di applicazione. Dunque,
essa è opzionale ma altamente desiderabile.
ATTENZIONE! Purtroppo mentre PHP
è indipendente dal browser che sta usando l'utente, lo stesso
non vale per Javascript. Ne segue che, quando si adotta la validazione
lato client, occorre controllare su vari tipi di browser che la
validazione funzioni bene, visto che non tutto si comporta esattamente
allo stesso modo con browser diversi.
Validazione batch della pagina di inserimento voli
Una prima soluzione al problema può essere data dallo script inserimento-validate-old.php. Questo controlla che il numero aereo e i codici aeroporto immessi dall'utente abbiano dei corrispettivo elementi nelle tabelle aerei e aeroporti. Qualora ciò non accada, invece di passare alla fase di inserimento viene visualizzata una pagina di errore.
È possibile tuttavia visualizzare gli errori in maniera più accattivante. Ad esempio, possamo modificare lo script in modo che, in caso di errore, venga rivisualizzata la pagina di inserimento dati, con in più l'elenco dei problemi che si sono verificati e con i campi di input già pre-riempiti. Si ottiene inserimento-validate.php.
In questo script abbiamo fatto uso di variabili di sessione per passare i valori immessi dall'utente dalla fase di controllo dati/inserimento alla fase di richiesta dati/visualizzazione errori. Una volta che queste variabili di sessione non servono più, è necessario eliminarle, e lo abbiamo fatto usando la seguente funzione:
void unset (mixed var1 [, mixed var [, mixed ...]])
: svuota le variabili che le vengono passate come parametro. È equivalente ad assegnarle il valore NULL
.
Una alternativa sarebbe stata quella di utilizzare session_destroy
, che però distrugge tutte le variabili di sessione. Nel caso ci fossero altre parti dell'applicazione che utilizzano variabili di sessione, questo potrebbe comprometterne il funzionamento. Ad esempio, nella applicazione airdb definitiva, la procedura di inserimento dovrà controllare che l'utente è autenticato (qui abbiamo tolto i controlli per semplicità). Eseguire una session_destroy
vorrebbe dire impedire il riconoscimento dell'utente.
Esercizio
Modificare inserimento-validate
in modo tale che, quando si verifica un errore, i campi di input che sono stati riempiti con i dati sbagliati vengano visualizzati in corsivo. A questo proposito, è possibile usare il tag <em>
.
Validazione interattiva della pagina di inserimento voli
Visto che non è scopo del corso insegnare il JavaScript,
mostriamo solo un esempio di come è possibile implementare un
controllo interattivo lato client. Ovviamente, non è immediato
controllare lato client se i valori immessi per il numero aereo o per i
codici dell'aeroporto sono già presenti nella base di dati
(anche se è possibile farlo). Per questo, controlliamo soltanto
che nel campo relativo al numero di aereo venga inserito un valore
numerico. Lo script che ci interessa è inserimento-js.php.
I file utilizzati in questa lezione: airdb3.sql,
error.php,
e .htaccess