Come realizzare un modulo contatti in PHP?
Negli articoli della guida sulla progettazione dei form, abbiamo visto tutti i vari elementi che compongono il markup degli elementi, come strutturarli in modo valido, e come integrare tali form con jQuery. In questa lezione vedremo come interfacciare un semplice modulo contatti con PHP, realizzando tutti i controlli da zero.
Partiremo da un semplice form, con quattro campi: Nome, Email, Sito Web e Messaggio, a cui applichiamo un foglio di stile, preso dall’articolo “Form Design”. Apri dunque il tuo editor preferito e crea il file contatti.php
, incollando il codice seguente:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Modulo contatti in PHP | Your Inspiration Web</title> <link rel="stylesheet" type="text/css" href="stile.css" /> </head> <body> <form action="" method="post" id="formYIW"> <fieldset> <legend><span>Inviaci un messaggio</span></legend> <ol> <li> <label for="nome">Nome <abbr title="campo obbligatorio">*</abbr></label> <input type="text" name="nome" id="nome" tabindex="1"/> </li> <li> <label for="email">Email <abbr title="campo obbligatorio">*</abbr></label> <input type="text" name="email" id="email" tabindex="2"/> </li> <li> <label for="sito">Sito web</label> <input type="text" name="sito" id="sito" tabindex="3"/> </li> <li> <label for="messaggio">Messaggio <abbr title="campo obbligatorio">*</abbr></label> <textarea name="messaggio" id="messaggio" rows="10" cols="30" tabindex="4"></textarea> </li> </ol> </fieldset> <p class="controls"> <input type="submit" name="submit" id="submit" value="Invia Mail" tabindex="5" /> </p> </form> </body> </html>
Questo form sarà il nostro punto di partenza per la creazione del codice PHP di supporto.
Mettiamoci in “azione”
La prima questione da risolvere è il valore da inserire nel campo action
del form. Possiamo operare due scelte: la prima prevede di utilizzare un file per ospitare il form che punterà ad un altro script, responsabile del processo di validazione. In caso di errore, si viene reindirizzati alla pagina contenente il form, altrimenti alla pagina di conferma.
La seconda scelta, invece, prevede di inserire sia il form che la logica per l’invio della mail in un unico script. Attraverso l’esame delle metodo di richiesta, si offre al browser una sezione diversa: se la richiesta è di tipo GET, viene mostrato il form; in caso contrario (ovvero in caso di richiesta POST), il form viene processato.
Ogni metodo ha i suoi pro e contro: ad esempio gli script multipli soffrono sul piano della manutenibilità. Infatti bisogna tener traccia di più file, e in caso di modifiche ad uno, bisognerà con buona probabilità modificare anche l’altro. D’altro canto, in molte circostanze la modularità è un punto di forza. Insomma, come spesso accade, non esiste il metodo migliore: dipende dalle circostanze.
Detto questo, in questo esempio la visualizzazione del form e la relativa gestione conviveranno nello stesso file. Dunque l’attributo action
dovrà puntare proprio a contatti.php
.
... <form action="contatti.php" method="post" id="formYIW"> <fieldset> <legend><span>Inviaci un messaggio</span></legend> ...
Voglio però fare una riflessione. Cosa accadrebbe se rinominassimo il file in modulo_contatti.php
? Esatto: il form non funzionerebbe più, e saremmo costretti a modificare il campo “action”. Esiste una soluzione più flessibile: attraverso l’array superglobale $_SERVER
possiamo delegare questo compito a PHP. Infatti tale array tiene traccia di tutti gli elementi che intervengono nell’interazione tra il Server e lo script, tra cui anche il nome dello script stesso. La variabile interessata è chiamata PHP_SELF
e possiamo integrarla nel form in questo modo:
... <form action="<?php $_SERVER['PHP_SELF'] ?>" method="post" id="formYIW"> <fieldset> <legend><span>Inviaci un messaggio</span></legend> ...
In questo modo il nostro form punterà sempre al file corretto, anche in caso di rinomina e/o spostamento dello stesso.
Parola d’ordine: modularità
Come ha spiegato molto bene Nando nel suo articolo rendere dinamiche alcune sezioni del proprio sito porta solo vantaggi. Ad esempio, potremmo voler riutilizzare questo form più di una volta sul sito; quindi lo sposteremo in un file separato, che chiameremo appunto form.php
. Tale file verrà poi incluso in contatti.php
tramite la direttiva require_once
, in questo modo:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Modulo contatti in PHP | Your Inspiration Web</title> <link rel="stylesheet" type="text/css" href="stile.css" /> </head> <body> <?php //include il form require_once 'form.php'; ?> </body> </html>
Come differenziare le richieste POST e GET?
Ora che ci siamo accertati che il nostro modulo sarà effettivamente inviato ad uno script in grado di gestirlo e richiamato da un file esterno, passiamo ad una questione più delicata, ovvero come fare per differenziare una richiesta POST da una GET.
Ogni volta che un form viene inviato con un metodo “post”, PHP crea automaticamente un array superglobale chiamato $_POST
, in cui sono contenute tutte le coppie nome-valore del form. Ad esempio, se abbiamo un campo con “email” in cui inseriamo “ciccio@formaggio.com” e inviamo il form, verrà creato l’array $_POST
e la variabile $_POST['email']
con un valore di “ciccio@formaggio.com”.
Dunque possiamo testare se è stato inviato il form controllando se è stata settata una di queste variabili, ad esempio quella relativa al pulsante di invio (“submit”):
... if(isset($_POST['submit'])){ //codice per processare il form } //include il form require_once 'form.php'; ?>
Processare le variabili POST
Il processo di gestione di un form passa attraverso due fasi: preparazione ed eventuale validazione delle variabili POST e successivo redirect allo script necessario (dipendente da se ci sono stati errori o meno).
Per la gestione delle variabili POST di questo esempio utilizzeremo tre array:
- “$expected”, che ospita i nomi dei campi che ci aspttiamo di ricevere. Questo serve per evitare che un utente malintenzionato possa modificare l’operato del nostro form, aggiungendo campi nascosti.
- “$required”, che ospita i nomi dei campi obbligatori.
- “$missing”, array inizialmente vuoto, che ospiterà eventuali campi obbligatori, ma non compilati.
Definiremo questi tre array in un file esterno settings.php
che poi includeremo in contatti.php
:
/* settings.php Elenca i campi che ci si aspetta di ricevere. Evita che qualcuno possa aggiungere dei campi non previsti */ $expected = array('nome','email','sito','messaggio'); //imposta i campi obbligatori $required = array('nome','email','messaggio'); //crea un array vuoto per i campi mancanti $missing = array();
//file contatti.php ... require_once 'settings.php'; if(isset($_POST['submit'])){ ...
Una volta fatto ciò, siamo pronti per esaminare l’array $_POST
. Il ragionamento che seguiremo è, per sommi capi:
- Controlla ogni variabile dell’array
$_POST
. - Elimina tutti gli spazi aggiuntivi.
- Se la variabile è vuota, ma è obbligatoria, aggiungi il suo nome all’array “$missing”.
- Altrimenti, se il campo è uno che ci aspettiamo (ovvero il nome è inserito nell’array “$expected”) crea una variabile, denominata come il campo.
In codice, questo viene reso così:
... if(isset($_POST['submit'])){ foreach ($_POST as $key => $value){ //elimina eventuali spazi aggiuntivi $temp = trim($value); //se è richiesta ma vuota aggiungila all'array missing if(!strlen ($temp) && in_array($key, $required)){ array_push($missing, $key); } //se il campo è aspettato, setta la variabile associata elseif(in_array($key, $expected)){ ${$key} = htmlentities($temp); //in questo caso crea $nome, $email, $sito, $commento } } ...
Quindi seguendo l’esempio, se un utente compila i campi “nome”,”email” e “messaggio” del form (quelli obbligatori), al termine dell’esecuzione del codice appena sopra otterremo le variabili $nome, $email e $messaggio, che potremo utilizzare nello script.
Nota che ho utilizzato la funzione htmlentities
per assicurarmi di effettuare l’escape dei caratteri sull’input: questo passo è molto importante. Infatti la regola d’oro della programmazione web potrebbe essere: non fidarsi mai dell’input dell’utente.
Come inviare una mail tramite php?
Ipotizziamo per un momento di avere i migliori utenti di tutto il web navigare sul nostro sito. Tali utenti, una volta trovatisi di fronte al form, lo compilano con precisione e in tutte le sue parti. In questo caso, potremmo quindi procedere direttamente all’invio della mail, non trovi?
Nel caso in cui un utente compili tutti i campi del form (o meglio compili i campi obbligatori), l’array “$missing” risulterà vuoto. Quindi se l’array “$missing” è vuoto, si può inviare l’email:
if ( empty($missing) ){ //Se l'array missing è vuoto, vuol dire che sono stati inseriti i valori //obbligatori. }
Per inviare le email, PHP dispone della funzione mail()
che ha la seguente sintassi:
mail($destinatario, $oggetto, $contenuto_email, $parametri_opzionali);
e restituisce TRUE o FALSE, rispettivamente in caso di corretto invio o in caso di errore. Un utile parametro opzionale da inserire potrebbe essere l’indirizzo email del mittente. Si può inserire facilmente in questo modo:
mail($destinatario, $oggetto, $contenuto_email, 'From: '. $email_mittente);
Ora costruiamo il messaggio da inserire nell’email: è sempre utile riportare tutti i campi del form anche nel messaggio, in modo da tenere sotto controllo chi ci invia email:
... if ( empty($missing) ){ $contenuto_email = "Nome: $nome\n\n"; //Queste variabili sono create nel passaggio precedente $contenuto_email .= "Email: $email\n\n"; $contenuto_email .= "Sito Web: $sito\n\n"; $contenuto_email .= "Messaggio:\n $messaggio\n\n"; //limita la lunghezza a 70 caratteri per la compatibilità $contenuto_email = wordwrap($contenuto_email,70); //invia l'email $mail_sent = mail($destinatario,$oggetto,$contenuto_email, 'From: '.$email); if($mail_sent){ //Se l'email viene inviata l'array missing non serve più quindi lo svuoto unset($missing); } ...
Come puoi vedere nel codice sopra ho inserito tutti i dati del form nella variabile “$contenuto_email”, ho poi limitato la lunghezza di riga a 70 caratteri, per essere certo che il messaggio sia leggibile da tutti i client, e poi ho memorizzato il risultato dell’invio (ti ricordo, TRUE o FALSE) nella variabile “$mail_sent”. Quest’ultima ci permetterà di “tracciare” l’invio e di sapere se è stato eseguito tutto correttamente. Il primo utilizzo è quello di cancellare l’array “$missing”: infatti se l’email è stata inviata tale array non serve più e lo script deve ritornare alle condizioni iniziali.
L’ultimo dettaglio da sistemare è l’inserimento di un destinatario e di un oggetto: infatti non abbiamo ancora definito questi elementi! Il posto ideale per inserirli è il file settings.php
, in modo da consentire una facile modifica, senza dover toccare una riga del codice di gestione:
//file settings.php //email del destinatario del form $destinatario = 'indirizzo@email.com'; //oggetto dell'email inviata $oggetto = 'Mail dal modulo contatti articolo YIW';
Come gestire errori e notifiche nella compilazione del modulo?
Evviva, il nostro form è perfettamente funzionante! Ma c’è un problema: con tutta probabilità non tutti gli utenti del nostro sito compileranno correttamente il form. Alcuni mancheranno dei campi obbligatori, e anche se abbiamo già gestito questa eventualità nel codice, non c’è nessuna notifica di errore. Anche l’invio dell’email non viene accompagnato da un messaggio di conferma. Inoltre un utente potrebbe compilare tutti i campi, ma ci potrebbero essere dei problemi con il server che impediscono il corretto funzionamento del form. È nostro compito prevedere e gestire tutte queste situazioni.
Iniziamo dal compito più semplice: l’inserimento di un messaggio di conferma del corretto invio. L’idea di base è quella di inserire tutti i messaggi di notifica e di errore in un’unica variabile, e mostrare tali messaggi solo se la variabile è settata. Inseriremo tali notifiche appena sopra il form, e chiameremo la variabile “$info_message”:
//file contatti.php ... //Mostra una notifica sia d'errore che di conferma if ( isset( $info_message ) && strlen( $info_message ) ) echo $info_message; //Include il form require_once 'form.php'; ...
Il passo successivo è quello di impostare “$info_message” in caso di corretto invio: possiamo farlo appena sotto la funzione “mail”:
... $mail_sent = mail($destinatario,$oggetto,$contenuto_email, 'From: '.$email); $info_message = '<p class="info">' . $info_mail_sent . '</p>'; ...
Come puoi vedere, ho creato un paragrafo con classe “info” (di cui modificherò l’aspetto tramite CSS) e utilizzato come corpo della notifica un’altra variabile “$info_mail_sent”. È sempre buona pratica avere un file di configurazione, da modificare senza dover per forza cercare nel codice contentente la logica dell’applicazione. Come si dice, “lontano dagli occhi, lontano dai pasticci” (forse non era questo il proverbio, ma calza a pennello). Inoltre tale pratica potrebbe risultare utile in caso di internazionalizzazione dell’applicazione. Quindi, come già avrai immaginato, definiremo questa variabile nel file settings.php
:
//Messaggio di conferma invio mail //Info message for correct mail sent $info_mail_sent = 'L\'email è stata inviata correttamente!.';
Adesso dobbiamo gestire il caso in cui non siano stati inseriti tutti i campi obbligatori. Questa eventualità occorre quando il form è stato inviato, l’array “$missing” è stato definito e non è vuoto:
... //se non sono stati immessi campi obbligatori if ( isset( $_POST['submit'] ) && isset($missing) && !empty($missing)) : $info_message = '<p class="error">' . $error_missing_fields . '</p>'; ...
Anche qui ho utilizzato una variabile definita in settings.php
“$error_missing_fields”:
//Messaggio d'errore per campi mancanti //Error message for missing fields $error_missing_fields= 'Per favore, completate tutti i campi del form indicati';
Il caso in cui ci sono errori con il server è invece caratterizzato dalla variabile “$mail_sent” settata a FALSE, dopo aver inviato il form:
... elseif ($_POST['submit'] && !$mail_sent) : //se ci sono stati problemi con l'invio della mail da parte del server $info_message = '<p class="error">' . $error_mail_server . '</p>'; endif; ...
Abbiamo realizzato quindi un semplice ma robusto sistema di notifiche. C’è ancora un ultimo dettaglio, però, di cui voglio parlarti.
Migliorare il form
Allo stato attuale il nosto form non è altro che semplice HTML, e non si adatta automaticamente alle varie situazioni. Ad esempio, in caso di un campo mancante e invio del form, tutti i campi vengono azzerati. Inoltre quelli mancanti non vengono evidenziati in alcun modo. Vediamo come implementare questi semplici casi d’uso.
Apriamo dunque il file form.php
ed analizziamo un campo (questo discorso è identico per tutti i campi, cambia solo il nome delle variabili):
<li> <label for="nome">Nome <abbr title="campo obbligatorio">*</abbr></label> <input type="text" name="nome" id="nome" tabindex="1" /> </li>
Il nostro obiettivo è quello di inserire una classe “error” se il campo è presente nell’array “$missing” (ovvero l’utente non ha compilato il campo) e di inserire il valore del campo, se è stato precedentemente compilato. Aggiungeremo dunque dei piccoli controlli all’interno del tag input:
<li> <label for="nome">Nome <abbr title="campo obbligatorio">*</abbr></label> <input type="text" name="nome" id="nome" tabindex="1" value="<?php if ( isset( $missing ) && isset($nome) ) echo $nome; ?>" class="<?php if (isset( $missing ) && in_array('nome',$missing)) echo 'error'; ?>"/> </li>
Ecco fatto: in questo modo i campi inseriti vengono preservati, e quelli mancanti vengono evidenziati da un bordo rosso, attraverso la classe error. Tale procedimento viene eseguito per ogni campo, facendo attenzione a modificare il nome della variabile e al campo “textarea”, che non accetta l’attributo “value”. Ecco dunque il risultato finale.
Considerazioni Finali
Naturalmente questo form non è altro che un punto di partenza: ci sono tante cose che è possibile migliorare, ad esempio l’aggiunta di un sistema di validazione dei vari campi (in questo esempio ci siamo limitati ad eseguire l’escape), oppure si potrebbe automatizzare la creazione del contenuto dell’email, in modo da farla adattare a qualsiasi form in modo automatico. Il bello della programmazione è che si può sempre migliorare. Scarica questo esempio e prova a migliorarlo, e magari postaci il tuo risultato, così da discuterne insieme.
DownloadQuesto esempio mostra anche che durante la progettazione, bisogna tener conto di tantissime variabili, e il rischio di mancare qualcosa è sempre in agguato. Da qui la domanda che mi pongo da sempre: “è meglio realizzare questi elementi ex novo, oppure poggiarsi ‘sulle spalle dei giganti’ e utilizzare qualche modulo già pronto?”. Tu cosa ne pensi?
- I form: elementi di base
- I form: struttura e aspetto
- I form: jQuery e considerazioni
- Come realizzare un modulo contatti in PHP
64 commenti
Trackback e pingback
[...] This post was mentioned on Twitter by Your Inspiration Web and nando pappalardo, Antonio Capuozzo. Antonio Capuozzo said: @YIW…
[...] essere interessato anche ai seguenti articoli:Come realizzare un modulo contatti in PHP? Negli articoli della guida sulla progettazione dei…