Développement d'applications Web avec LAMP

Document d'accompagnement pour le cours 420-KB9-LG

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 :

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 :

Veuillez remplir S.V.P.

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 :

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.

Veuillez remplir S.V.P.

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 null. Un champ de formulaire vide n'est pas null mais forme une chaîne de longueur zéro.

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 :
  • " " (espace ordinaire);
  • "\t" (tabulateur);
  • "\n" (fin de ligne),
  • "\r" (retour de chariot);
  • "\0" (le caractère NUL);
  • "\v" (tabulateur vertical).
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>

Essayez l'application

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>

Essayez l'application

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 :

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

AVERTISSEMENT

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 :

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 :

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>