Valider un formulaire complexe en PHP

1 message   •   Page 1 sur 1
Mammouth du PHP | 19672 Messages

08 janv. 2006, 11:55

Validation en PHP d'un formulaire complexe.

Dans la très grande majorité des sites internet, on a des formulaires. Les sites dynamisés par PHP ne font pas exception à cette règle, d'autant moins qu'un site dynamique implique le plus souvent des échanges d'informations avec une base de données. Mais il faut valider les informations qu'on envoie dans cette base, ne serait-ce que pour éviter des problèmes d'injection SQL au plan de la sécurité ou bien encore l'envoi de documents vides.

Ce que vous ne verrez pas

On ne traitera pas ici des échanges avec les bases de données. On ne verra en fait pas l'utilisation que vous faites des données récupérées en dehors d'un affichage à l'écran, ce qui en fin de compte est déjà un traitement en soi. Libre à chacun d'adapter selon ses besoins.

Notez également qu'il est tout à fait possible d'effectuer une validation préalable tout aussi complète en JavaScript, ce que nous ne verrons pas ici.

Ce que vous devez connaître

Il est impératif de connaître la construction d'un formulaire en (X)HTML, rien ne sera précisé sur ce point, mais vous devez pouvoir suivre le code du formulaire et vous y retrouver sans trop de difficultés.

Ce que vous allez voir

Vous allez voir un code complet et autonome de formulaire comprenant presque toutes les type champs qu'on trouve habituellement dans un formulaire. "Presque" seulement puisqu'il y manque encore en particulier le champ de type "file".

Cependant, vous verrez comment on traite un formulaire sur une seule et même page, comment on récupère les valeurs envoyées, comment on ré-affiche un formulaire incomplet ou comportant des données invalides en conservant dans les zones de saisies ce qui a été inscrit par l'internaute, en laissant cochées les cases qu'il avait cochées ou sélectionné l'élément de la liste déroulante qu'il avait choisie.

Vous verrez également comment valider une adresse de courriel ou une url grâce à des expresions régulières. Mais sur ce point, je vous recommande un petit tour sur le tuto que nous a offert Ripat sur le sujet.

Inspirez-vous de ce code pour élaborer vos propres formulaires. Les amateurs noteront aussi que la mise en page est faite sans tableaux HTML. Pourtant vous verrez que l'affichage n'a rien de désordonné.
<?php
/** ******************************************************************************
 * Formulaire Gabarit
 * Ce script n'a pas d'autres prétentions que de montrer comment valider les
 * différents champs d'un formulaire.
 * Tout est améliorable, ne vous en privez surtout pas, adaptez-le selon vos
 * propres besoins. N'en prenez que des morceaux ou bien ajoutez-en d'autres.
 * Ce script est offert tel quel sans garantie aucune.
 * Je me suis efforcé de largement commenter chaque élément à l'intention de
 * ceux qui découvrent les joies du PHP.
 * Date de création : 11 Mars 2003
 * Dernière modification le 08 Janvier 2006
 * Auteur : Cyrano.
 * Courriel : cyrano at phpfrance point com
 * _______________________________________________
 * Ce qui se conçoit bien s'énonce clairement, si
 * moi j'ai compris, alors vous le pouvez aussi.
 * ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 * ******************************************************************************* */
/**
 * Comme il s'agit de XHTML, encadrement de la balise xml pour un affichage
 * normal sans message d'erreur de PHP
 */
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n";
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Date de création: 11-03-2003 -->
<!-- Mise à jour: 05-01-2006 -->
<head>
<title>Formulaire d'ajout à un annuaire (par exemple)</title>
<meta name="author" content="Cyrano" />
<meta name="generator" content="Zend Studio et WebExpert" />
<style type="text/css">
/* <![CDATA[ */
body {text-align: center; background-color: #99c; color: #333;}
#page {width : 520px; position: absolute; top: 1em; left: 50%; margin-left: -300px; color: inherit; background-color: #ccf; border: 1px solid #339}
p, blockquote {text-align: left; background-color: #9cc; color: #ccc;}
h3 {font-family: verdana, helvetica, sans-serif; text-align: center;}
p, label {font-family: verdana, helvetica, sans-serif; font-size: 10pt; font-weight: bold; padding-left: 5px; text-align: left; background-color: transparent; color: #333333;}
.block {font-size: 9pt; font-weight: normal; color: #630; background-color: inherit}
p.choix {text-align: right;}
fieldset {width: 500px; color: inherit; background-color: #fc6; padding: 0.5em; text-align: right; border: 3px double #339; margin: 0}
textarea {font-family: verdana, helvetica, sans-serif; font-size: 10pt; border: 1px solid #066; width: 249px; height:60pt; background-color: #ffff99; color: #333333;}
select {font-family: verdana, helvetica, sans-serif; font-size: 10pt; border: 1px solid #066; width: 249px; height:17pt; background-color: #ffff99; color: #333333;}
input {border: 1px solid #066; background-color: #ff9; color: inherit}
input.cases {width: 249px;}
input.verif {width: 150px;}
div.c3 {text-align:center; margin-top: 1em;}
.c2 {color: #f00; background-color: inherit; text-align: center; font-weight: bold; display: inline;}
.c1 {color: #f00; background-color: inherit; font-weight: bold;}
.legende_elmt {float: left;}
/* ]]> */
</style>
</head>
<body>
<div id="page">
<?php
// Fonction qui sera utilisée pour le traitement des cases à cocher:
function test($choix)
{
    $retour = false;
    $nb_msk = (isset($musik)) ? count($musik) : 0;
    for ($i = 0; $i < $nb_msk; $i++)
    {
        if($choix == $musik[$i])
        {
            $retour = true;
        }
    }
    return $retour;
}

/**
 * On commence par vérifier si le bouton soumettant le formulaire a été
 * cliqué, "envoi" étant l'attribut "name" du bouton "submit"
 * Sinon, on saute à la ligne 255 de ce code.
 */
if(isset($_POST['envoi']))
{
    /* Récupération des données du formulaire */
    $prenom    = isset($_POST['prenom'])    ? trim($_POST['prenom'])    : "";
    $nom       = isset($_POST['nom'])       ? trim($_POST['nom'])       : "";
    $telephone = isset($_POST['telephone']) ? trim($_POST['telephone']) : "";
    $email     = isset($_POST['email'])     ? trim($_POST['email'])     : "";
    $url       = isset($_POST['url'])       ? trim($_POST['url'])       : "";
    $lang      = isset($_POST['lang'])      ? $_POST['lang']            : "";
    $ville     = isset($_POST['ville'])     ? trim($_POST['ville'])     : "";
    $remark    = isset($_POST['remark'])    ? trim($_POST['remark'])    : "";
    $musik     = isset($_POST['musik'])     ? $_POST['musik']           : null;
    $age       = isset($_POST['age'])       ? $_POST['age']             : "";

    /**
     * Définition des variables servant au traitement de l'adresse électronique et du numéro de
     * téléphone: on utilise ici des expressions régulières.
     */
    $valid = "#^[^-_\.][a-z0-9-_\.]+[^-_\.]@[^-_\.][a-z0-9-_\.]+[^-_\.]\.[a-z]{2,4}$#";
    $phone = "#^\d{6,10}$#";
    /**
     * Définition des variables servant au traitement de l'url:
     */
    /**
     * Validité d'une url 
     */
    $validurl = "#^(?:(?:https?|ftp)://)?(?:w{3}\.)?[^\W]?[\w-\.]*[^\W]?\.[a-z]{2,4}(?:/(?:~?[^\W]?[\w-\./]*[^\W]?(?:\.[a-z]{2,4})?(?:\?\w+=\w+(?:(?:&|&)\w+=\w+)*)?)?)?$#i";

    /**
     * Traitement de vérification des champs vides ou invalides (téléphone et/ou email et/ou url)
     * Conditions de mauvaises réponses (champ vide par exemple)
     */
    if($url && ($url == "http://"))
    {
        $url = "";
    }
    if ($prenom == '' || $nom == '' || $email == '' || $telephone == '' || !(preg_match($phone,$telephone)) || $email == '' || !(preg_match($valid, $email)) || ($url && (!(preg_match($validurl, $url)))))
    {
        /* Action à adopter */
?>
				<h3>Informations incomplètes</h3>
				<p>Un (ou plusieurs) champ(s) obligatoire(s) n'a(ont) pas été correctement rempli(s).</p>
<?php
        if ($prenom == '')
        {
            /* Si le champ "prénom" est vide, */
            print "<p>Vous n'avez pas précisé votre prénom</p>\n";
        }
        if ($nom == '')
        {
            /* Si le champ "nom" est vide, */
            print "<p>Vous n'avez pas précisé votre nom</p>\n";
        }
        if ($telephone == '')
        {
            /* Si le champ "téléphone" est vide, */
            print "<p>Vous n'avez pas précisé votre numéro de téléphone</p>\n";
        }
        if (($telephone) && !(preg_match($phone,$telephone)))
        {
            print "<p>Le numéro de téléphone doit comporter seulement des chiffres, de 6 à 10 chiffres sans espaces ni tirets</p>\n";
        }
        if(!$email)
        {
            /* Si le champ "adresse électronique" est vide, */
            print "<p>Vous avez omis de mentionner une adresse électronique !</p>\n";
        }
        if(($email) && !(preg_match($valid, $email))) /* Si il y a une adresse inscrite mais invalide */
        {
            /* On vérifie LES DEUX conditions réunies (avec le sugne "&&"): si on ne vérifie que la validité, en ne
            mettant pas d'adresse dans le formulaire, on obtient l'affichage des deux messages, or l'adresse à
            ce moment là n'est pas invalide, elle est absente: le message d'invalidité ne s'applique donc pas. */
            print "<p>L'adresse électronique saisie est invalide.</p>\n";
        }
        if($url && (!(preg_match($validurl, $url))))
        {
            print "<p>L'adresse du site Web saisie est invalide.</p>\n";
        }

        /**
         * Si les vérifications ont généré des erreurs, affichage du formulaire
         * contenant les données déjà saisies.
         */
?>
<form action="<?php echo($_SERVER['PHP_SELF']); ?>" method="post">
  <fieldset>
  <label><span class="legende_elmt">Votre prénom : </span><span class="c2">*</span> <input type="text" name="prenom" maxlength="40" class="cases" value="<?php echo $prenom ?>" /></label><br />
  <label><span class="legende_elmt">Votre Nom de famille : </span><span class="c2">*</span> <input type="text" name="nom" maxlength="40" class="cases" value="<?php echo $nom ?>" /></label><br />
  <label><span class="legende_elmt">Votre numéro de téléphone : </span><span class="c2">*</span> <input type="text" name="telephone" maxlength="40" class="cases" value="<?php echo $telephone ?>" /></label><br />
  <label><span class="legende_elmt">Votre adresse électronique : </span><span class="c2">*</span> <input type="text" name="email" maxlength="40" class="cases" value="<?php echo $email ?>" /></label><br />
  <label><span class="legende_elmt">Votre site Web : </span><input type="text" name="url" maxlength="120" class="cases" value="<?php echo $url ?>" onfocus="if(this.value==''){this.value='http://';}" /></label><br />
  <label><span class="legende_elmt">Votre ville : </span><input type="text" name="ville" maxlength="40" class="cases" value="<?php echo $ville ?>" /></label><br />
  <p class="choix"><label><span class="legende_elmt">Votre langue de préférence : </span></label>
  Français <input type="radio" name="lang" value="français"<?php echo(($lang=="français") ? " checked=\"checked\"": null); ?> /><br />
  Anglais <input type="radio" name="lang" value="anglais"<?php echo(($lang=="anglais") ? " checked=\"checked\"": null); ?> /><br />
  Allemand <input type="radio" name="lang" value="allemand"<?php echo(($lang=="allemand") ? " checked=\"checked\"": null); ?> /><br />
  Italien <input type="radio" name="lang" value="italien"<?php echo(($lang=="italien") ? " checked=\"checked\"": null); ?> /></p>
  <p class="choix">
  <label><span class="legende_elmt">Votre musique préférée : </span></label>
  Classique <input type="checkbox" value="Classique" name="musik[]"<?php echo((test("Classique")) ? " checked=\"checked\"": null); ?> /><br />
  Populaire <input type="checkbox" value="Populaire" name="musik[]"<?php echo((test("Populaire")) ? " checked=\"checked\"": null); ?> /><br />
  Rock & Roll <input type="checkbox" value="Rock&Roll" name="musik[]"<?php echo((test("Rock&Roll")) ? " checked=\"checked\"": null); ?> /><br />
  New age <input type="checkbox" value="Newage" name="musik[]"<?php echo((test("Newage")) ? " checked=\"checked\"": null); ?> /><br />
  Pas de musique <input type="checkbox" value="Pas de musique" name="musik[]"<?php echo((test("Pas de musique")) ? " checked=\"checked\"": null); ?> />
  </p>
  <label ><span class="legende_elmt">Votre tranche d'âge : </span>
  <select name="age">
  <option value="moins de 15 ans"<?php echo(($age=="Moins de 15 ans") ? " selected=\"selected\"" : null); ?>>moins de 15 ans</option>
  <option value="de 16 à 25 ans"<?php echo(($age=="de 16 à 25 ans") ? " selected=\"selected\"" : null); ?>>de 16 à 25 ans</option>
  <option value="de 26 à 35 ans"<?php echo(($age=="de 26 à 35 ans") ? " selected=\"selected\"" : null); ?>>de 26 à 35 ans</option>
  <option value="de 36 à 45 ans"<?php echo(($age=="de 36 à 45 ans") ? " selected=\"selected\"" : null); ?>>de 36 à 45 ans</option>
  <option value="46 ans ou plus"<?php echo(($age=="46 ans ou plus") ? " selected=\"selected\"" : null); ?>>46 ans ou plus</option>
  </select></label><br />
  <label><span class="legende_elmt">Notes additionnelles : </span>
  <textarea name="remark" cols="20" rows="5"><?php echo $remark ?></textarea></label>
  <div class="c3">
  <input type="submit" class="verif" name="envoi" value="Envoyer" />&nbsp;<input type="reset" class="verif" value="Recommencer" />
  </div>
  </fieldset>
</form>
<?php
    }
    else
    {
        /**
         * Si aucun des champs obligatoire n'est vide et les données sont valides:
         * Traitement des données : ce sujet n'est pas abordé ici, on ne voit que la validation.
         * Néanmoins, l'affichage des données recueillies est un traitement en soi.
         * Libre à chacun d'adapter pour faire un autre type de traitement.
         */
        $href_email = str_replace("@", "%40", $email);
        // Affichage du message final des informations reçues
        print "<h3>Merci ! Voici les informations que vous avez fournies</h3>\n";
        print "<p>Informations sur le contact:</p>\n";
        print "<p>". $prenom ." ". $nom ."<br />\n";
        print "On peut vous joindre au ".$telephone."<br />\n";
        if($ville != "")
        {
            print "Vous résidez à ".$ville."<br />\n";
        }
        print "On peut vous envoyer un courrier électronique à: <a href=\"mailto:". $prenom ."%20". $nom ."%20%3c". $href_email ."%3e\">".$email."</a><br />\n";
        print "On rejoint votre site en cliquant sur ce lien <a href=\"".$url."\" title=\"".$url."\">>> ICI <<</a><br />\n";
        print "Vous préférez parler en ".$lang."<br />\n";
        if($musik)
        {
            /* Affichage des valeurs des différentes cases cochées si au moins une est cochée: */
            print "Vos préférences musicales : ";
            for ($i = 0; $i < count($musik); $i++)
            {
                echo $musik[$i]." - ";
            }
            print "<br />\n";
        }
        else
        {
            /* Si aucune case n'a été cochée, affichage d'une autre message. */
            print "Vous n'avez aucune préférence en matière de musique<br />\n";
        }
        print "Vous êtes de la génération ".$age."</p>\n";
        if ($remark) // Si du texte a été saisi dans la boite textarea:
        {
            print "<p>Vos remarques: </p>\n"; // Affichage du texte saisi dans la boite textarea après traitement de mise en page.
            print "<p class=\"block\">".nl2br(stripslashes($remark))."</p>\n";
        }
        else /* Si aucun texte n'a été saisi, alors affichage d'un message alternatif. */
        {
            print "<p>Vous n'avez mentionné aucune information supplémentaire.</p>\n";
        }
        print("<p>Retour vers le formulaire de base, cliquez <a href=\"". $_SERVER['PHP_SELF'] ."\" title=\"Retour vers le formulaire\">ICI</a></p>");
    }
}
/**
 * Si cette page s'ouvre pour la première fois sans que le bouton soumettant le formulaire n'ait
 * été cliqué, alors on affiche le formulaire normalement
 */
else
{
?>
<h3>Complétez les informations pour ajouter votre nom à la liste des membres</h3>
<p>Notez que les champs précédés d'une <span class="c1">*</span> doivent obligatoirement être remplis.</p>
<form action="<?php echo($_SERVER['PHP_SELF']); ?>" method="post">
  <fieldset>
  <label><span class="legende_elmt">Votre prénom : </span><span class="c2">*</span> <input type="text" name="prenom" maxlength="40" class="cases" value="" /></label><br />
  <label><span class="legende_elmt">Votre Nom de famille : </span><span class="c2">*</span> <input type="text" name="nom" maxlength="40" class="cases" value="" /></label><br />
  <label><span class="legende_elmt">Votre numéro de téléphone : </span><span class="c2">*</span> <input type="text" name="telephone" maxlength="40" class="cases" value="" /></label><br />
  <label><span class="legende_elmt">Votre adresse électronique : </span><span class="c2">*</span> <input type="text" name="email" maxlength="40" class="cases" value="" /></label><br />
  <label><span class="legende_elmt">Votre site Web : </span><input type="text" name="url" maxlength="120" class="cases" value="" onfocus="this.value='http://'" /></label><br />
  <label><span class="legende_elmt">Votre ville : </span><input type="text" name="ville" maxlength="40" class="cases" value="" /></label><br />
  <p class="choix"><label><span class="legende_elmt">Votre langue de préférence : </span></label>
  Français <input type="radio" name="lang" value="français" checked="checked" /><br />
  Anglais <input type="radio" name="lang" value="anglais" /><br />
  Allemand <input type="radio" name="lang" value="allemand" /><br />
  Italien <input type="radio" name="lang" value="italien" /></p>
  <p class="choix">
  <label><span class="legende_elmt">Votre musique préférée : </span></label>
  Classique <input type="checkbox" value="Classique" name="musik[]" /><br />
  Populaire <input type="checkbox" value="Populaire" name="musik[]" /><br />
  Rock & Roll <input type="checkbox" value="Rock&Roll" name="musik[]" /><br />
  New age <input type="checkbox" value="Newage" name="musik[]" /><br />
  Pas de musique <input type="checkbox" value="Pas de musique" name="musik[]" />
  </p>
  <label ><span class="legende_elmt">Votre tranche d'âge : </span>
  <select name="age">
  <option value="moins de 15 ans">moins de 15 ans</option>
  <option value="de 16 à 25 ans">de 16 à 25 ans</option>
  <option value="de 26 à 35 ans">de 26 à 35 ans</option>
  <option value="de 36 à 45 ans">de 36 à 45 ans</option>
  <option value="46 ans ou plus">46 ans ou plus</option>
  </select></label><br />
  <label><span class="legende_elmt">Notes additionnelles : </span>
  <textarea name="remark" cols="20" rows="5"></textarea></label>
  <div class="c3">
  <input type="submit" class="verif" name="envoi" value="Envoyer" />&nbsp;<input type="reset" class="verif" value="Recommencer" />
  </div>
  </fieldset>
</form>
<?php
}
?>
</div>
</body>
</html>
Note importante

Ce tuto vous est offert, mais ne m'interpellez pas directement si vous ne comprenez pas un détail. Lisez bien tous les commentaires du code, ils ont leur importance. Posez vos questions sur le forum, si je ne suis pas présent, d'autres répondront aussi bien que moi.

Bon code
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

1 message   •   Page 1 sur 1