Una delle operazioni piรน comuni di interazione tra un sito web ed i suoi utenti, consiste nella compilazione di moduli (o form). In questo articolo vedremo in che modo chiunque puรฒ implementare un form con PHP allโinterno del proprio sito web per effettuare una serie di operazioni di vario tipo e natura come, ad esempio, lโinvio di email o lโinserimento di dati in un database.
Introduzione: i moduli in HTML
Per chi non lo sapesse, un modulo รจ composto da un insieme di tag HTML il cui scopo รจ raccogliere gli input dellโutente: possiamo avere caselle di testo, strumenti di selezione, strumenti di scelta (alternativa e multipla), strumenti per lโupload di file, ecc. Attraverso tutti questi strumenti, lโutente inserisce dei dati ed esprime delle preferenze che potranno essere oggetto di archiviazione e/o di elaborazione da parte di uno script.
In questa sede non ritengo opportuno tornare su concetti propri del linguaggio di markup ed invito, pertanto, il lettore interessato a leggere questa lezione della nostra Guida ad HTML per una rinfrescata su <form> e sugli altri tag per la creazione di moduli.
Quello che a noi interessa, in questa sede, รจ di capire in che modo uno script PHP puรฒ raccogliere ed elaborare i dati raccolti mediante un form.
Trasmissione dei dati: i metodi GET e POST
I form possono inviare dati ad una pagina web mediante due diverse metodologie di trasporto che prendono il nome di GET e POST.
Il metodo utilizzato deve essere specificato dallo sviluppatore allโinterno del codice HTML del form attraverso lโattributo method in questo modo:
<form method="post" action="mioscript.php">
...
...
...
</form>
Sulla base di quanto specificato nellโattributo method ("get" o "post") dovremo conformare il codice della pagina che andrร a processare la richiesta (ovvero il file specificato nellโattributo action).
Quando i dati vengono inviati col metodo GET, questi sono trasmessi sotto forma di query-string. In altre parole, quando il form verrร inviato dallโutente, il browser effettuerร un redirect sulla pagina specificata nel parametro action accodando โ allโinterno della URL โ i valori dei diversi campi del modulo, in questo modo:
mioscript.php?campo1=valore1&campo2=valore2&campo3=valore3
Come potete vedere i valori sono trasmessi "in chiaro" alla pagina web ricevente sotto forma di coppie di parametri/valori, tra loro concatenate mediante il simbolo della "E commerciale" (&).
Viceversa, se il modulo viene inviato col metodo POST, tutti questi valori saranno trasmessi alla pagina web in modo "trasparente" per lโutente, nel senso che i parametri ed i rispettivi valori non saranno visibili nella URL della pagina, ma saranno inviati allโinterno della "parte invisibile" della trasmissione HTTP che avviene tra il client ed il server.
La raccolta dei dati inviati tramite un modulo da parte di uno script PHP
Fino ad ora abbia fatto un semplice ripasso circa il funzionamento dei moduli HTML ed il modo in cui consentono di trasmettere dei dati ad una specifica pagina web (uno script). Vediamo ora in che modo PHP รจ in grado di raccogliere i dati che sono stati raccolti ed inviati tramite un form.
Per farlo PHP dispone di due variabili globali corrispondenti ai due metodi di invio visti poco sopra. Le due variabili in questione prendono il nome di $_GET e $_POST. Queste due variabili sono valorizzate in automatico da PHP e contengono, sotto forma di array, tutti i valori ricevuti tramite il metodo GET ed il metodo POST (per maggiori informazioni si faccia riferimento a questa lezione della nostra Guida PHP).
Il funzionamento di queste variabili รจ identico: essendo delle array, รจ possibile recuperare il valore di un dato parametro semplicemente specificandone il nome tra parentesi quadra, in questo modo:
// recupero il valore del parametro 'campo1' trasmesso mediante query-string (metodo GET)
$campo1 = $_GET['campo1'];
// recupero il valore del parametro 'campo1' trasmesso mediante il metodo POST
$campo1 = $_POST['campo1'];
In altre parole: il valore del campo, presente nel nostro modulo HTML, avente come nome "campo1" puรฒ essere recuperato da PHP sfruttando, appunto, le variabili globali $_GET o $_POST (a seconda del method specificato nel tag <form>).
Facciamo un semplicissimo esempio pratico. Supponiamo di avere un form che chiede allโutente di inserire il proprio indirizzo email:
<form method="post" action="mioscript.php">
Inserisci il tuo indirizzo email<br>
<input type="text" name="email"><br>
<input type="submit" value="Invia Modulo">
</form>
Vediamo quindi il corrispondente script PHP che, al submit del form, raccoglie questa informazione e โ molto banalmente โ la stampa a video:
<?php
$email = $_POST['email'];
echo 'Il tuo indirizzo email รจ: ' . $email;
>
Lโoutput prodotto sarร qualcosa di questo tipo:
Il tuo indirizzo email รจ: fake@email.com
Oltre alle variabili $_GET e $_POST, PHP offre anche una terza opzione: la variabile $_REQUEST. Questa variabile puรฒ essere utilizzata quando non si sa se il dato viene recapitato tramite il metodo GET o il metodo POST, essendo questa variabile una sorta di "mix" di entrambe:
// recupero il valore del parametro 'campo1' (sia GET che POST)
$campo1 = $_REQUEST['campo1'];
Si faccia attenzione perรฒ, in quanto questa variabile contiene โ oltre ai valori trasmessi via GET e POST โ anche i valori presenti nella variabile globale $_COOKIE. A titolo personale non ne consiglio lโutilizzo se non in casi di effettivo bisogno.
Creare un modulo di contatto in PHP
Una delle esigenze tipiche quando si crea un sito web consiste nella creazione di un modulo di contatto che consenta agli utenti di inviarci delle comunicazioni. Molto spesso mi viene chiesto "Come si crea un modulo di contatto in HTML?" La risposta รจ: "Non si puรฒ". HTML, infatti, รจ un linguaggio di markup โ e non di scripting โ e non offre pertanto la possibilitร di gestire autonomamente questo tipo di esigenze.
Eโ in questa prima e comunissima esigenza che PHP rivela la sua potenza e versatilitร nellโinterazione coi moduli. Vediamo, quindi, come creare un semplicissimo modulo di contatto con PHP, partendo dal markup HTML:
<form method="post" action="formmail.php">
Inserisci il tuo nome<br>
<input type="text" name="nome"><br>
Inserisci il tuo indirizzo email<br>
<input type="text" name="email"><br>
Scrivi un messaggio:<br>
<textarea name="msg"></textarea><br>
<input type="submit" value="Invia Modulo">
</form>
Vediamo ora il codice PHP del nostro file "formmail.php":
<?php
// Recupero i valori inseriti nel form
$nome = $_POST['nome'];
$email = $_POST['email'];
$msg = $_POST['msg'];
// compilo un messaggio combinando i dati recuperati dal form
$testo = "Nome: " . $nome . "\n"
. "Email: " . $email . "\n"
. "Messaggio:\n" . $msg;
// uso la funzione mail di PHP per inviare questi dati al mio indirizzo di posta
mail('mia@email.com', 'Messaggio dal mio sito web', $testo);
// Mostro un messaggio di conferma all'utente
echo 'Grazie per averci contattato!';
?>
Quello proposto รจ un esempio rudimentale che, tuttavia, assolve bene il compito di mostrare in che modo PHP riesca ad interagire coi moduli per generare, ad esempio, una email allโatto del loro submit. Per maggiori informazioni sulle caratteristiche e le potenzialitร della funzione mail() di PHP vi invito a leggere questa lezione della nostra Guida a PHP.
Archiviazione dei dati allโinterno di un database MySQL
Altra funzionalitร tipica nella gestione dei moduli con PHP, consiste nellโarchiviazione dei dati (inseriti dallโutente nei vari campi di un form) allโinterno di una base dati. Per semplictร faremo riferimento al database MySQL essendo il piรน diffuso in combinazione con questo linguaggio di scripting lato server.
Ancora una volta partiamo dal markup HTML di un semplice modulo di raccolta dati anagrafici per la registrazione ad un dato servizio:
<form method="post" action="registrazione.php">
Inserisci il tuo nome<br>
<input type="text" name="nome"><br>
Inserisci il tuo cognome<br>
<input type="text" name="cognome"><br>
Inserisci il tuo indirizzo email<br>
<input type="text" name="email"><br>
Scegli una password<br>
<input type="text" name="pass"><br>
<input type="submit" value="Registrati">
</form>
Vediamo ora il sorgente dello script che effettua materialmente la registrazione dellโutente salvandone i dati allโinterno di un database:
<?php
// Recupero i valori inseriti nel form
$nome = $_POST['nome'];
$cognome = $_POST['cognome'];
$email = $_POST['email'];
$password = $_POST['pass'];
// dati di connessione al mio database MySQL
$db_host = 'localhost';
$db_user = '...';
$db_pass = '...';
$db_name = '...';
// connessione al DB utilizzando MySQLi
$cn = new mysqli($db_host, $db_user, $db_pass, $db_name);
// verifica su eventuali errori di connessione
if ($cn->connect_errno) {
echo "Connessione fallita: ". $cn->connect_error . ".";
exit();
}
// definisco la query di inserimento dati
$sql = "INSERT INTO utenti (nome, cognome, email, password) VALUES ("
. "'" . $nome . "',"
. "'" . $cognome . "',"
. "'" . $email . "',"
. "'" . $password . "')"
// esecuzione della query
if (!$cn->query($sql)) {
echo "Errore della query: " . $cn->error . ".";
}else{
echo "Registrazione effettuata correttamente.";
}
// chiusura della connessione
$cn->close();
Ancora una volta sembra tutto piuttosto semplice: PHP recupera i dati inseriti dallโutente allโinterno del modulo, poi li utilizza allโinterno di una query SQL che viene eseguita per effettuare lโinserimento dati allโinterno del database (per maggiori informazioni sullโinterazione tra PHP e MySQL consiglio la lettura di questa guida). Ancora una volta, perรฒ, quello proposto non รจ niente di piรน che un esempio scolastico la cui finalitร non va oltre a quella puramente didattica: mettere in produzione questo script, infatti, sarebbe alquanto rischiosoโฆ
Il problema della sicurezza dei dati inviati coi moduli
Sino ad ora ci siamo limitati a mostrare in che modo รจ possibile gestire i form con PHP allโinterno di "un mondo ideale" dove lโutente fa sempre e solamente quello che lo sviluppatore vorrebbeโฆ peccato che nella realtร dei fatti non รจ sempre cosรฌ.
Il buon sviluppatore, infatti, รจ ben cosciente dei rischi che si nascondono allโinterno dei moduli e โ piรน in generale โ sa quanto sia importante effettuare unโaccurata verifica e validazione di tutti i dati ricevuti in input dagli utenti.
Nellโesempio precedente, infatti, sarebbe piuttosto semplice, per un malintenzionato, attuare un attacco mediante la tecnica della SQL Injection: sarebbe sufficiente valorizzare ad hoc uno dei campi del nostro modulo di iscrizione, infatti, per compromettere la riservatezza e lโintegritร del nostro database!
Quando si parla di gestione dei form con PHP, quindi, non si puรฒ non affrontare la tematica della sicurezza dei moduli al fine di prevenire attacchi di SQL Injection e Cross-Site Scripting (solo per citare le due minacce piรน diffuse).
A tal fine la raccomandazione รจ sempre la stessa: assicuratevi, prima di processare un modulo, che i dati inseriti al suo interno siano conformi ai valori che vi attendete da un utilizzatore corretto. Per fare un esempio: allโinterno di un ipotetico campo "email" deve essere inserito un valido indirizzo email, cosรฌ come allโinterno di un ipotetico campo "etร " deve essere scritto un valore di tipo numerico.
A tal fine PHP offre numerose funzioni ad hoc, vediamo di seguito un esempio di sequenza di controllo dei dati inseriti in un form:
// Recupero i valori inseriti nel form
$nome = $_POST['nome'];
$cognome = $_POST['cognome'];
$email = $_POST['email'];
$eta = $_POST['eta'];
// verifico che tutti i campi siano stati compilati
if (!$nome || !$cognome || !$email || !$eta) {
echo 'Tutti i campi del modulo sono obbligatori!';
}
// verifico che il nome non contenga caratteri nocivi
elseif (!preg_match('/^[A-Za-z \'-]+$/i',$nome)) {
echo 'Il nome contiene caratteri non ammessi';
}
// verifico che il cognome non contenga caratteri nocivi
elseif (!preg_match('/^[A-Za-z \'-]+$/i',$cognome)) {
echo 'Il cognome contiene caratteri non ammessi';
}
// verifico se un indirizzo email รจ valido
elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo 'Indirizzo email non corretto';
}
// verifico che il campo etร sia numerico, non sia inferiore di 1 e maggiore di 120
elseif (!is_numeric($eta) || $eta < 1 || $eta > 120) {
echo 'Campo etร non corretto';
}else{
// A QUESTO PUNTO POSSO PROCESSARE IL FORM
// ...
// ...
// ...
}
Altra utile precauzione consiste nellโutilizzo di funzioni di escape dei caratteri speciali prima dellโinserimento dei dati, ricevuti in input, allโinterno di una query SQL: esempio tipico sono le funzioni addslashes() e, soprattutto, mysql_real_escape_string() e mysqli_real_escape_string(). In alternativa รจ possibile (e consigliabile) utilizzare la sintassi dei Prepared Statements di MySQLi che garantiscono una gestione sicura ed efficiente dei dati inseriti allโinterno delle query SQL.
Altre funzioni molto utili quando si lavora coi form con PHP sono htmlspecialchars(), htmlentities() e strip_tags(): si tratta di tre funzioni native di PHP che รจ bene ricordare ed utilizzare nelle situazioni in cui รจ necessario prevenire attacchi di tipo XSS (Cross-Site Scripting) come, ad esempio, nei guestbook e nei forum o โ piรน in generale โ in tutte quelle situazioni in cui i dati passati in input da un utente vengono incorprati in una pagina visibile anche ad altri.
Conclusioni
PHP รจ un linguaggio estremamente potente e versatile grazie al quale non รจ particolarmente complicato gestire i dati ricevuti in input dagli utenti tramite dei moduli HTML. Se la sintassi di base puรฒ apparire piuttosto semplice, tuttavia, รจ opportuno ricordarsi che una implementazione "basica" puรฒ prestare il fianco a numerosi inconvenienti tra cui, soprattutto, quello di cadere vittima di qualche attacco informatico.
Nella gestione dei form con PHP, quindi, รจ opportuno prendere le dovute precauzioni ed effettuare sempre i necessari controlli al fine di verificare che i dati inseriti siano conformi a quelli attesi.