Formation PUB010 : PHP, 2018 La validation d'un formulaire Web

16.4 Valider un formulaire côté serveur avec PHP


La validation d'un formulaire Web est une tâche complexe. Il faut en effet s'assurer que les données entrées par l'usager correspondent au format attendu, qu'elles soient valables et qu'elles ne compromettent pas la sécurité du site Web.

Normalement, une fois que l'usager a cliqué sur le bouton de soumission, les données entrées devraient correspondre au format attendu puisqu'une validation a déjà été effectuée côté client.

Cependant, comme cette validation peut être désactivée, il est absolument nécessaire de refaire la validation côté serveur.

Voici les étapes qui permettent de bien valider les données d'un formulaire avec PHP.

▼Publicité Le texte se poursuit plus bas

Vérifier le format attendu

Vérifier si les données sont valables

Une donnée sera valable si elle correspond à une valeur acceptée. Pour vous assurer que les données soient valables :

Si au moins une erreur est détectée

Si au moins une erreur est détectée, il faut afficher un message d'erreur puis permettre à l'usager de corriger la situation.

Le message doit indiquer clairement chacune des erreurs rencontrées.

Enregistrer les données sans compromettre la sécurité

Quand les données ont passé toutes les validations, on peut procéder à l'enregistrement ou aux opérations requises pour finaliser le traitement du formulaire.

Avant de procéder, il est important de sécuriser le code afin de limiter les risques que les informations entrées par l'usager soient la source d'une attaque (en anglais, on dira sanitize inputs).

Ainsi, avant ou après nous être assurés que les données correspondent au format attendu et qu'elles sont valables, il faut les désinfecter. 

Deux précautions s'imposent :

  • Afin de se protéger des attaques XSS, les données saisies dans le formulaire devront être converties avec htmlspecialchars() avant l'enregistrement ou avant d'être affichées à l'écran. Grâce à cette précaution, aucune balise <script> et aucun apostrophe ou guillemet ne pourra causer de comportement inattendu.
  • Afin de se protéger des injections SQL, les requêtes SQL qui utilisent des données provenant d'un formulaire devront être faites à l'aide de requêtes préparées.

Confirmation à l'usager

Bien important, une fois le traitement complété, un message devra indiquer à l'usager si l'opération a été réussie ou non.

Un exemple vaut mille mots

Voici un algorithme qui vous aidera à ne rien oublier lorsque vous traitez un formulaire.

Le formulaire est hétéroclite mais il permet d'illustrer différentes validations.

Cet algorithme est bien sûr perfectible. Libre à vous de l'utiliser, de le perfectionner ou de développer votre propre algorithme.

PHP

// *** protection XSS ******************************************************************
foreach ($_POST as $element => $valeur) {
    $_POST[$element] = htmlspecialchars($valeur);
}
 
// *** initialisation des variables pour clarifier le code *****************************
$modele = $_POST['modele'];
$description = $_POST['description'];
$annee = $_POST['annee'];
$courriel = $_POST['courriel'];
$codePostal = $_POST['codepostal'];
$prix = $_POST['prix'];
 
// *** validations côté serveur ******************************************************** 
$message = '';
 
// format attendu : champs obligatoires
if ('' == $modele) {
    $message .= 'Le modèle est requis.<br />';
}
 
if ('' == $description) {
    $message .= 'La description est requise.<br />';
}
 
// format attendu : longueur des champs
if (!empty($annee) && 4 != mb_strlen($annee)) {
    $message .= 'L\'année, lorsque fournie, doit comporter exactement 4 caractères.<br />';
}
 
if (mb_strlen($description) > 100) {
    $message .= 'La description ne doit pas comporter plus de 100 caractères.<br />';
}
 
// format attendu : courriel
if (!filter_var( $courriel, FILTER_VALIDATE_EMAIL)) {
    $message .= 'Le courriel n\'est pas valide. Il doit être au format unnom@undomaine.uneextension.<br /> &nbsp; &nbsp; Il doit comporter un seul caractère @.<br /> &nbsp; &nbsp; Ce caractère doit être suivi d\'un nom de domaine qui contient au moins un point puis une extension.<br /> &nbsp; &nbsp; Les caractères spéciaux ne sont pas acceptés.<br />';}
 
// format attendu : code postal canadien
if(!preg_match("/^[ABCEGHJKLMNPRSTVXYabceghjklmnprstvxy][0-9][ABCEGHJKLMNPRSTVWXYZabceghjklmnprstvwxyz] ?[0-9][ABCEGHJKLMNPRSTVWXYZabceghjklmnprstvwxyz][0-9]$/i",$codePostal)) {
    $message .= 'Le code postal n\'est pas valide. Il doit être au format A9A 9A9.<br /> &nbsp; &nbsp; Les lettres D, F, I, O, Q et U ne sont pas acceptées.<br /> &nbsp; &nbsp; Les lettres W et Z sont acceptées mais pas en première position.<br />';
}

// format attendu : téléphone
if(!preg_match("/^[0-9]{3} [0-9]{3}-[0-9]{4}$/", $telephone)) {
    $message .= 'Le téléphone n\'est pas valide. Il doit être au format 999 999-9999.<br />';
}
 
// données valables : champs numériques
if (!empty($annee) && !ctype_digit($annee)) {
    $message .= 'L\'année n\'est pas valide. Lorsqu\'elle est fournie, elle doit être un entier.<br />';
}
 
//données valables : valeur décimale
if (!empty($prix)) {
    // si on n'a pas besoin de vérifier la valeur maximale, omettre le else
    if (!is_numeric($prix)) {
        $message .= 'Le prix n\'est pas valide. Lorsqu\'il est fourni, il doit être un nombre qui peut comporter une partie décimale.<br />';
    } else {
        // si on vérifie avec l'expression régulière, pas besoin de vérifier le is_numeric()
        if (!preg_match("/^[0-9]{1,3}([.,][0-9]{1,2})?$/", $prix)) {
            $message .= 'Le prix n\'est pas valide. Lorsqu\'il est fourni, il doit être au format 999.99.<br />';
        }
    }
}
 
// données valables : clés étrangères
$requete = "...";   // voir "Valider la clé étrangère saisie dans un formulaire avec PHP"
...
if ($stmt->num_rows == 0) {   // sous WordPress, on fera plutôt if ( $wpdb->num_rows > 0 )
    $message .= 'Le modèle choisi n\'est pas valide.<br />';
}
 
if ('' != $message) {
    // Cet extrait de code fonctionne seulement pour un site PHP vanille 
    // *** affichage du message ********************************************************
    require 'include/entete.inc';
    echo "<div class='messageerreur'>$message</div>";
 
    // *** réaffichage du formulaire avec les données qui y ont été saisies ************
    ...

   require 'include/pied-page.inc';
 
} else {
 
    // *** enregistrement *************************************************************
    ... 
}

Veuillez noter que le contenu de cette fiche vous est partagé à titre gracieux, au meilleur de mes connaissances et sans aucune garantie.
Par Christiane Lagacé
Dernière révision le 20 novembre 2021
Merci de partager !

Site fièrement hébergé chez A2 Hosting.

Soumettre