Dans le cas d'erreur de saisie, pour que l'utilisateur ne perde pas les saisies qu'il a déjà faites, il faut ré-afficher le formulaire avec les valeurs entrées et un message d'erreur si la valeur n'est pas bonne.

traitement auto-soumission

Pour réaliser cela on utilise la méthode de l'auto-soumission (rien à voir avec des pratiques sado-maso) : la page responsable de l'affichage du formulaire s'envoie à elle même le contenu saisi, effectue les validations et en cas d'erreur retombe dans son traitement d'affichage.

Pour pouvoir afficher le formulaire avec des messages d'erreur, il faut que le traitement des erreurs de saisie soit fait avant l'affichage.

On a donc un organigramme de traitement dont la première action va être de tester si on est dans une phase d'initialisation (1er affichage du formulaire) ou dans une phase de soumission.

Démonstration avec notre formulaire simplifié :

Exemple : gestion des erreurs de saisie
<?php require('bib_fonctions.php'); htmlDebut('Gestion des erreurs'); $zones = array('txtNom' => '', 'txtId' => '', 'txtCursus' => ''); $errs = array(); // Phase 1er affichage if (! isset($_POST['btnSubmit'])) { afficherForm($zones, $errs); exit(); } // Phase de soumission // Validation des données reçues $x = trim($_POST['txtNom']); $long = strlen($x); if ($long < 2 || $long > 50) { $errs['txtNom'] = 'Nom de 2 à 50 caractères.'; } $clean = strip_tags($x); if ($clean != $x) { $errs['txtNom'] .= 'Pas de tags HTML.'; } $zones['txtNom'] = $x; if (estEntier($_POST['txtId']) && estEntre($_POST['txtId'], 1, 99999999)) { $zones['txtId'] = (int) $_POST['txtId']; } else { $zones['txtId'] = $_POST['txtId']; $errs['txtId'] = 'Nombre entier de 1 à 99999999'; } $x = trim($_POST['txtCursus']); $clean = strip_tags($x); if ($clean != $x) { $errs['txtCursus'] = 'Pas de tags HTML.'; } $zones['txtCursus'] = $x; // Si il y a des erreurs on réaffiche le formulaire if (count($errs) != 0) { afficherForm($zones, $errs); exit(); } // OK pas d'erreur htmlInfo('Validation OK. Redirection vers autres page'); htmlFin(); //_________________________________________________ /** * Gestion de l'affichage du formulaire * * @param array $zones nom/valeurs des zones * @param array $errs nom/message d'erreur des zones */ function afficherForm($zones, $errs) { htmlProteger($zones); htmlProteger($errs); echo '<form method="post" ', 'action="', $_SERVER['PHP_SELF'], '" >'; echo '<label>Nom</label>', '<input type="text" name="txtNom" ', 'value="', $zones['txtNom'], '">'; if (isset($errs['txtNom'])) { echo '<br>', $errs['txtNom']; } echo '<label>Identifiant</label>', '<input type="password" name="txtId" ', 'value="', $zones['txtId'], '">'; if (isset($errs['txtId'])) { echo '<br>', $errs['txtId']; } echo '<label>Cursus</label>', '<textarea name="txtCursus">', $zones['txtCursus'], '</textarea>'; if (isset($errs['txtCursus'])) { echo '<br>', $errs['txtCursus']; } echo '<p><input type="reset" name="btnReset" ', 'value=" Effacer ">', '<input type="submit" name="btnSubmit" ', 'value="Envoyer">', '</p></form>'; htmlFin(); } ?>

Quelques explications sur le code du script.

    $zones = array('txtNom' => '',
    	   'txtId' => '',
    	   'txtCursus' => '');
    $errs = array();

Le script commence par initialiser 2 tableaux qui contiennent respectivement les zones à afficher dans le formulaire et les zones en erreur (vide pour le moment).

L'initialisation des zones est ici reduite, mais on pourrait utiliser n'importe quelles valeurs, en particulier celles obtenues par la lecture d'une base de données.

    // Phase 1er affichage
    if (! isset($_POST['btnSubmit'])) {
    	afficherForm($zones, $errs);
    	exit();
    }

Nous testons ensuite si c'est le premier passage avec un affichage "simple" du formulaire que nous réalisons alors par l'appel de la fonction afficherForm() et nous arrêtons ensuite le script avec exit car le travail est terminé pour cette phase.
Ce qui définit cette phase c'est l'absence du bouton de soumission (<input type="submit" name="btnSubmit" ', 'value="Envoyer">) dans le tableau $_POST.

Si le bouton de soumission du formulaire est présent dans $_POST la phase de vérification est éxécutée avec les tests de validation étudiés précédemment.

Extrait

    $x = trim($_POST['txtNom']);
    $long = strlen($x);

    if ($long < 2 || $long > 50) {
    	$errs['txtNom'] = 'Nom de 2 à 50 caractères.';
    }
    $clean = strip_tags($x);
    if ($clean != $x) {
    	$errs['txtNom'] .= 'Pas de tags HTML.';
    }
    $zones['txtNom'] = $x;

Si des erreurs sont trouvées, un message est stocké dans le tableau $errs. La clé du message est le nom de la zone provoquant l'erreur. Cela permettra de retrouver facilement l'erreur éventuellement attachée à la zone si nous avons besoin de ré-afficher le formulaire.
Les informations saisies sont stockées dans le tableau $zones avec comme clé le nom de la zone et comme valeur ce qui a été reçu, tel que.

Quand toutes les vérifications sont faites, il suffit de tester la longueur du tableau $errs pour savoir ce que nous devons faire.

    if (count($errs) != 0) {
    	afficherForm($zones, $errs);
    	exit();
    }

    // OK pas d'erreur
    htmlInfo('Validation OK. Redirection vers autres page');
    htmlFin();

Si le tableau $errs n'est pas vide, nous réaffichons le formulaire par l'appel de la fonction afficherForm() et nous arrêtons ensuite le script avec exit.
Si aucune erreur n'a été détectée, on peut faire le traitement des informations reçues comme par exemple une insertion dans une base de données, utiliser les informations pour faire des recherches, des calculs, etc.

La fonction afficherForm() prend en compte l'affichage du formulaire avec des echo de code HTML. Elle contient 2 éléments importants : la valeur de l'attribut action du tag form et la protection des valeurs affichées.

    function afficherForm($zones, $errs) {
    	htmlProteger($zones);
    	htmlProteger($errs);

    	echo '<form method="post" ',
    			'action="', $_SERVER['PHP_SELF'], '" >';

    	echo '<label>Nom</label>',
    			'<input type="text" name="txtNom" ',
    			'value="', $zones['txtNom'], '">';

    	if (isset($errs['txtNom'])) {
    		echo '<br>', $errs['txtNom'];
    	}

    	echo '<label>Identifiant</label>',
    			'<input type="password" name="txtId" ',
    			'value="', $zones['txtId'], '">';

    	if (isset($errs['txtId'])) {
    		echo '<br>', $errs['txtId'];
    	}

    	echo '<label>Cursus</label>',
    			'<textarea name="txtCursus">',
    			$zones['txtCursus'],
    			'</textarea>';

    	if (isset($errs['txtCursus'])) {
    		echo '<br>', $errs['txtCursus'];
    	}

    	echo '<p><input type="reset" name="btnReset" ',
    		'value=" Effacer ">',
    		'<input type="submit" name="btnSubmit" ',
    		'value="Envoyer">',
    		'</p></form>';

    	htmlFin();
    }

Nous utilisons la fonction htmlProteger() de notre bibliothèque bib_fonctions.php pour afficher les choses, sans qu'elles ne provoquent de problème si elles contiennent du code HTML malveillant ou que l'on ne veut pas qu'il soit interprété.

La deuxième chose à remarquer est la façon dont le formulaire se soumet à lui-même avec l'utilisation de l'élément PHP_SELF du tableau $_SERVER. Cet élément contient la référence (url) du script en train de s'exécuter. On peut donc l'utiliser l'auto-soumission.

    echo '<form method="post" ',
    		'action="', $_SERVER['PHP_SELF'], '" >';

Le reste du code de la fonction est une simple génération de code HTML qui pourrait bien sûr être traité d'autres façons (templates, fonctions dédiées, méthodes d'objets).