Traitement de formulaires
Dernière mise à jour le 8 octobre 2022
Méthodes de requêtes et paramètres
Dans cette section nous allons examiner les différences entre requêtes GET et POST.
Méthode GET
Dans le document précédent (protocole HTTP), nous avons surtout utilisé la méthode GET.
Vous utilisez souvent cette méthode, sans peut-être le savoir, puisque c'est celle qui s'applique dans les cas suivants :
- clic sur un hyperlien (balise
<a>
); - entrée directe d'un URL dans la barre d'adresse du navigateur;
- méthode par défaut dans les formulaires HTML.
Dans tous les cas précédents, c'est une requête GET qui envoyée au serveur.
Exemple :
<a href="lotr/hobbits.html">À propos des hobbits</a> --> GET lotr/hobbits.html HTTP/1.1
Pour envoyer des données (on dit aussi "paramètres") au serveur via une requête GET sans utiliser de formulaire, la technique consiste à ajouter celles-ci à la suite de l'URL.
Dans l'exemple suivant, on envoie d'abord aucun paramètre au script bonjour.php, puis on en lui envoie deux :
Code HTML | Sortie dans le navigateur |
---|---|
<a href="formulaires/bonjour.php">Dire bonjour</a> |
Dire bonjour |
<a href="formulaires/bonjour.php?nom=Sacquet&prenom=Frodon">Dire bonjour</a> |
Dire bonjour |
Les données sont ajoutées à L'URL sous forme de couples nom-valeur. Remarquez l'utilisation des caractèrese ?
et &
.
Cliquez sur les deux hyperliens du tableau et observez l'URL affiché dans la boîte d'adresse du navigateur :
https://prog101.com/lamp/formulaires/bonjour.php https://prog101.com/lamp/formulaires/bonjour.php?nom=Sacquet&prenom=Frodon
Maintenant, amusez-vous à changer la valeur des paramètres dans la barre d'adresse du navigateur et observez le résultat. N'oubliez pas de presser la touche Enter pour générer une nouvelle requête au serveur.
Il y a évidemment une manière plus simple de générer une requête HTTP, c'est d'utiliser un formulaire HTML.
L'exemple suivant est celui d'un formulaire qui permet de générer la même requête GET (avec ou sans paramètres) :
<form action="formulaires/bonjour.php"> <fieldset> <legend>Veuillez remplir S.V.P.</legend> <label for="prenom">Prénom</label> <input type="text" id="prenom" name="prenom"> <br> <label for="nom">Nom</label> <input type="text" id="nom" name="nom"> <br> <input type="submit"> </fieldset> </form>
Entrez des données et observez l'URL affiché dans la barre d'adresse du navigateur :
Remarque : même s'il s'agit de la méthode HTTP par défaut dans les formulaires, il est recommandé de l'indiquer.
Ainsi les deux balise suivantes sont équivalentes, bien que la seconde soit préférable :
<form action="formulaires/bonjour.php"> <form action="formulaires/bonjour.php" method="GET">
Méthode POST
Comme nous l'avons vu, une requête GET, qu'elle soit générée par un hyperlien ou par un formulaires, ajoute les informations en paramètres à l'URL.
La présence de ces données dans l'URL a deux inconvénients majeurs :
-
Le premier de ces inconvénients touche la sécurité. Les données étant visibles dans la barre d'adresse du navigateur une fois le formulaire envoyé, une personne malveillante pourrait se pencher au-dessus de votre épaule et voir ces données, même si le formulaire comme tel n'est plus affiché.
De plus, les URL étant habituellement enregistrés dans l'historique du navigateur, les paramètres le sont aussi.
-
L'autre inconvénient est lié à la taille limite d'un URL. Même si en général cette taille avoisine les 2000 caractères, cette limite peut facilement être atteinte (pensez à du texte entré dans un élément
<textarea>
).De plus, cette taille limite n'est pas la même pour tous les navigateurs et pourraient changer dans l'avenir.
C'est pourquoi dans le cas des formulaires on utilise généralement la méthode POST.
Le formulaire suivant utilise la méthode POST. Essayez-le et observez l'absence de paramètres dans la barre d'adresse lors de l'affichage de la réponse.
Il s'agit du même formulaire que précédemment, sauf qu'on y a ajouté une indication à l'intention du navigateur pour qu'il utilise la méthode POST lors de l'envoi des données
<form action="formulaires/bonjour.php" method="POST">
Récupérer les paramètres d'une requête
Un script peut facilement récupérer les données qui lui sont envoyées via la requête GET grâce aux tableaux associatifs $_GET
et $_POST
(selon la méthode HTTP utilisée). Ces tableaux sont automatiquement remplis avec les valeurs passées en paramètres à la requête.
Puisque ces tableaux sont des "superglobales", elles sont accessibles dans tous les contextes du script et il n'est pas nécessaire d'utiliser le mot-clé global
pour y accéder depuis une fonction.
La clé à utiliser dans ces tableaux correspond à la valeur de l'attribut name
dans le formulaire. Exemple :
<form action="formulaires/bonjour.php" method="POST"> ... <input type="text" id="prenom" name="prenom"> ... <input type="text" id="nom" name="nom"> ...
<?php $visiteur = $_POST['prenom'] . " " . $_POST['nom'];
Le tableau $_REQUEST
, plus rarement utilisé, rassemble les contenus des tableaux $_GET
, $_POST
et $_COOKIE
.
Validation des paramètres
Vous devez ABSOLUMENT valider les paramètres d'une requête. Et cela même si la méthode utilisée est POST. Il est trop facile de contourner la validation HTML ou JavaScript codée dans le formulaire.
Il faut garder à l'esprit qu'un formulaire n'est qu'une façon parmi d'autres de construire une requête HTTP. Rien n'empêche de construire une requête manuellement avec un outil comme PuTTY ou par programmation.
Les fonctions suivantes sont utilisées pour la validation des données de formulaires. À vous de les utiliser judicieusement :
Fonction | Utilisation |
---|---|
isset() |
Détermine si une variable est déclarée et est différente de On détruit une variable avec la fonction unset()é |
empty() |
Détermine si une variable est considérée comme vide. Dans le contexte d'un formulaire, une variable est considérée comme vide si elle n'existe pas ou s'il s'agit d'une chaîne vide. |
strip_tags() |
Supprime toutes les balises HTML et PHP contenues dans la chaîne. Voir le document sur les fichiers. |
trim() |
Supprime les espaces blancs (whitespace characters) en début et fin de chaîne. Les espaces blancs sont :
|
strlen() |
Détermine la taille d'une chaîne. |
htmlentities() |
Convertit tous les caractères éligibles en entités HTML. Par exemple, le code echo htmlentities("<h1>Le titre</h1>"); affichera :
<h1>Le titre</h1>
et non :
Le titre
|
Formulaire et script dans la même page
Pour donner meilleure allure à nos applications, évitons d'avoir une page HTML et une page PHP. Rassemblons tout le code dans un même fichier PHP et utilisons le variable $_SERVER['REQUEST_METHOD']
.
Cette variable, extraite du tableau associatif $_SERVER
que nous verrons en détail plus tard, permet de savoir par quelle méthode le script a été invoqué.
L'exemple suivant sera commenté en classe :
<?php // ce code sera toujours exécuté $methode = "GET"; if ($_SERVER['REQUEST_METHOD'] == "POST") { <-- Attention! "POST" écrit en majuscules! // ce code sera exécuté seulement suite au clic sur le bouton du formulaire $methode = "POST"; } ?> <!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <title>Sans titre</title> </head> <body> <p> Arrivé ici par la méthode <?= $methode ?> </p> <form action="index.php" method="post"> <input type="submit"> </form> </body> </html>
Exemple complet
Voyons une mini-application écrites avec un fichier HTML et un fichier PHP.
Fichier HTML contenant uniquement le formulaire :
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <title>Bonjour</title> <style>...</style> </head> <body> <form action="bonjour.php" method="get"> <fieldset> <legend>Veuillez remplir S.V.P.</legend> <label for="prenom">Prénom</label> <input type="text" id="prenom" name="prenom"> <br> <label for="nom">Nom</label> <input type="text" id="nom" name="nom"> <br> <input type="submit"> </fieldset> </form> </body> </html>
Fichier PHP contenant uniquement le traitement des données :
<?php $visiteur = $_GET['prenom'] . " " . $_GET['nom']; // si la chaîne est vide if (strlen(trim($visiteur)) == 0) { $visiteur = "Inconnu(e)"; } $message = "Bonjour $visiteur! Bienvenue à votre cours de PHP!"; ?> <!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <title>Bonjour</title> <style>...</style> </head> <body> <p class="message"> <?= $message ?> </p> <p> <button onclick="history.back()">Retour</button> </p> </body> </html>
Rassemblons maintenant tout le code au sein d'un même fichier PHP :
<?php
$message = "";
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$visiteur = $_POST['prenom'] . " " . $_POST['nom'];
// si la chaîne est vide
if (strlen(trim($visiteur)) == 0) {
$visiteur = "Inconnu(e)";
}
$message = "Bonjour $visiteur! Bienvenue à votre cours de PHP!";
}
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Bonjour - version 2</title>
<style>...</style>
</head>
<body>
<p class="message">
<?= $message ?>
</p>
<form method="post">
<fieldset>
<legend>Veuillez remplir S.V.P.</legend>
<label for="prenom">Prénom</label>
<input type="text" id="prenom" name="prenom">
<br>
<label for="nom">Nom</label>
<input type="text" id="nom" name="nom">
<br>
<input type="submit">
</fieldset>
</form>
</body>
</html>
Le code en vert n'est exécuté qu'à la suite d'une requête POST.
Du point de vue de l'utilisateur, cette seconde version (à une seule page) est nettement plus agréable à utiliser.
Veuillez noter les points suivants par rapport à la première version :
- le formulaire utilise maintenant la méthode POST;
- l'attribut
action
de la baliseform
a été supprimé, ce qui fait que les données de formulaires sont automatiquement envoyées au script courant.
Rediriger l'utilisateur vers une autre page
Lors du traitement de données de formulaires côté serveur, il est souvent nécessaire de diriger l'utilisateur vers une certaine page en fonction des données fournies.
Pensez au formulaire d'authentification sur prog101.com dans lequel vous fournissez votre code d'admission (ou votre adresse courriel) et votre mot de passe. Si le script d'authentification détermine que les données sont valides, la page d'accueil de votre cours est affichée. Dans le cas contraire, vous êtes redirigés à nouveau vers le formulaire d'authentification.
La redirection se fait au niveau du protocole HTTP en retournant l'entête de réponse Location
.
Exemple :
HTTP/1.1 302 Found Content-Type: text/html Location: login.php ...
Pour générer un entête de réponse HTTP, on utilise la fonction header().
Le script suivant affiche un formulaire où l'utilisateur chosit vers quel site Web il veut aller :
<?php $message = ""; if ($_SERVER['REQUEST_METHOD'] == "POST" && isset($_POST['destination'])) { if ($_POST['destination'] == "linuxclg") { header('Location: http://linuxclg.com'); exit; } else if ($_POST['destination'] == "profdinfo") { header('Location: https://mapage.clg.qc.ca/profdinfo'); exit; } else { $message = "Je reste ici!"; } } ?> <!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <title>Exemple de redirection</title> </head> <body> <form method="POST"> <label for="linuxclg">LinuxCLG</label> <input type="radio" id="linuxclg" name="destination" value="linuxclg"> <br> <label for="profdinfo">Prof d'info</label> <input type="radio" id="profdinfo" name="destination" value="profdinfo"> <br> <label for="ici">Je reste ici</label> <input type="radio" id="ici" name="destination" value="ici"> <br> <button type="submit">Aller vers...</button> </form> <p><?= $message ?></p> </body> </html>
Sortie :
Remarque : ce code est complet et fonctionnel. Vous pouvez le "copier-coller" sur le serveur et l'essayer.
Attention! C'est une erreur courante que d'insérer un espace avant les deux points :
header('Location: /exemples'); // oui header('Location : /exemples'); // non
Terminons en signalant qu'un appel à la fonction header() devrait toujours être suivi de l'instruction exit
.
Le comportement normal d'un navigateur est d'obéir à l'entête de redirection et de ne pas tenir compte du code HTML qui suit. C'est pourquoi on néglige partois le exit
.
Il faut savoir toutefois qu'il existe (et qu'on peut créer facilement) des outils Web qui ne tiennent pas compte des entêtes et qui pourraient potentiellement afficher tout le code HTML qui suit l'appel à la fonction header().
C'est donc une sage précaution de terminer immédiatement l'exécution d'un script après la redirection avec l'instruction exit
.
Exercice (formatif) à faire en classe
Rassemblez les exercices 2 et 3 du document sur les fichiers pour que tout soit contenu (formulaire et tableau) dans un même fichier PHP. Inspirez-vous de l'exemple précédent.
Questions et exercices de révision
Nous ne fournirons pas les réponses à ces questions pour deux bonnes raisons. La première est que celles-ci se trouvent dans les notes de cours. La seconde est que, dans certains cas, ce serait presque donner la réponse à des questions d'examen.
Question 1
Pour chacun des cas suivants, dites si la requête HTTP sera de type GET ou POST :
- clic sur un hyperlien (balise
<a>
) - entrée directe d'un URL dans la barre d'adresse du navigateur
- méthode par défaut dans les formulaires HTML
Question 2
Donnez l'URL complet pour invoquer le script "test.php" dans le répertoire racine du serveur à l'adresse "160.153.49.69" et en lui passant les paramètre suivants :
- pseudo : bob
- courriel : elvis@hotmail.com
Question 3
Quelle méthode est la plus sécuritaire pour envoyer des données de formulaire, GET ou POST? Expliquez pourquoi.
Question 4
Donnez le code PHP pour rediriger l'utilisateur vers "http://salihayacoub.com/" (voir https://prog101.com/lamp/formulaires.php#redirection).
Question 5
Donnez la forme abrégée (sans l'instruction "echo") du code PHP dans la ligne suivante :
<p>Gandalf était entré dans la pièce accompagné de <?php echo $hobbit; ?></p>