Développement d'applications Web avec LAMP

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

Traitement de formulaires

Dernière mise à jour le 29 octobre 2025

Méthodes de requêtes et paramètres

Dans cette section, nous allons examiner les différences entre les deux requêtes HTTP les plus utilisées : GET et POST.

Si la notion de "requête HTTP" ne vous dit rien, c'est probablement que le protocole HTTP n'a pas encore été abordé en classe, ce qui ne saurait tarder.

Méthode GET

Nous avons jusqu'ici utilisé surtout la méthode GET. Ce qui est normal, 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.

Par exemple, le fait de cliquer sur l'hyperlien suivant :

<a href="lotr/hobbits.html">À propos des hobbits</a>

va envoyer la requête HTTP suivante au serveur :

GET lotr/hobbits.html HTTP/1.1

Remarque : la mécanique des requêtes HTTP a été ou sera abordée dans un autre tutoriel.

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 précédent 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 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 variables "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 effectuée en HTML ou en JavaScript dans le document.

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 logiciel (exemple : PuTTY - nous verrons bientôt comment) 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, nous éviterons d'avoir une page HTML et une page PHP. Nous allons rassembler tout le code dans un même fichier PHP et utiliser la 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 rouge 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 403 Accès non autorisé
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.

La fonction filter_var()

Cette section n'est pas incluse dans le mini-test 2.

Toute donnée transmise à un script (champ de formulaire, paramètre d'URL, etc) doit être validée ou, au minimum, nettoyée.

La mauvaise réputation de PHP côté sécurité n'est pas justifiée étant donné que le langage offre nativement une puissante fonction pour valider et nettoyer les données. Cette fonction se nomme filter_var().

La validation et le nettoyage d'une donnée sont deux choses différentes.

Validation

La validation consiste à vérifier qu'une donnée correspond à un patron bien défini et qu'elle est utilisable comme telle.

Prenons le cas d'une adresse courriel. Pour être valide, celle-ci doit répondre aux critères énoncés dans la RFC 3696.

Voyons comment valider une adresse courriel reçue via un formulaire à l'aide de filter_var() :

$courriel = $_POST['courriel'];

$courriel_valide = filter_var($courriel, FILTER_VALIDATE_EMAIL);

Le deuxième paramètre indique que l'on cherche à vérifier si le premier paramètre est bien une adresse courriel. La fonction retournera la chaîne si l'adresse est valide, FALSE autrement.

Une donnée valide peut être utilisée sans risque de malfonctionnement ou d'atteinte à la sécurité de l'application.

bob.gratton@clg.qc.cq      bob.gratton@clg.qc.cq (valide)
bob.gratton@<clg.qc.ca>    FALSE (invalide)

Nettoyage

Le nettoyage d'une donnée consiste à l'expurger de tous ses caractères invalides.

$courriel = $_POST['courriel'];

$courriel_valide = filter_var($courriel, FILTER_SANITIZE_EMAIL);

La résultante d'un nettoyage ne sera pas nécessairement une donnée valide. Elle pourrait même dans certains cas causer un malfonctionnement de l'application, mais ne devrait pas causer de problèmes de sécurité.

Si l'application ne cherche pas à utiliser la donnée dans une opération spécifique, mais seulement à la stocker, le nettoyage peut être suffisant.

bob.gratton@clg.qc.cq    bob.gratton@clg.qc.cq (valide)
bob.gratton.clg.qc.ca    bob.gratton.clg.qc.cq (invalide, mais non dangereux)

Il existe une dizaine de filtres de validation :

FiltreRetourne TRUE si est...
FILTER_VALIDATE_BOOLEAN
FILTER_VALIDATE_BOOL
un booléen
FILTER_VALIDATE_DOMAINun nom de domaine
FILTER_VALIDATE_EMAILune adresse courriel
FILTER_VALIDATE_FLOATun nombre à virgule flottante
FILTER_VALIDATE_INTun nombre entier
FILTER_VALIDATE_IPune adresse IP
FILTER_VALIDATE_MACune adresse MAC
FILTER_VALIDATE_REGEXPune expression régulière
FILTER_VALIDATE_URLune URL

Et autant de filtres de nettoyage. Consultez la documentation pour en savoir plus.

En guise de résumé

Appliquez ce traitement à tous les intrants de vos applications Web :


[client]
Validation du formulaire
(validation HTML / JavaScript)

[serveur]
Nettoyage et validation des paramètres
(PHP, expressions régulières, filtres, etc.)

[base de données]
Requêtes préparées ou procédures stockées

Et ne faites jamais confiance à l'utilisateur!

Exploits of a Mom
Exploits of a Mom

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. Vous pouvez essayer la solution.

Défi : ajoutez à cette page un hyperlien ou un bouton pour vider la base de données.

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>

Question 6  NOUVEAU

Retournez à la question 2 et donnez le code pour récupérer à l'intérieur du script PHP la valeur des deux paramètres reçus et les afficher.

Question 7  NOUVEAU

Donnez la fonction manquante (c'est la même dans les deux cas).

$toto = NULL;

if (! ... ($toto)) {
  echo "La variable toto est nulle";
}

if (! ... ($tata)) {
  echo "La variable tata est inexistante";
}

Question 8  NOUVEAU

Donnez la fonction manquante (c'est la même dans les trois cas).

$toto = NULL;
$titi = "  ";

if ( ... ($toto)) {
  echo "La variable toto ne contient rien";
}

if ( ... ($tata)) {
  echo "La variable tata ne contient rien";
}

if ( ... (trim($titi))) {
  echo "La variable titi ne contient rien";
}

Question 9  NOUVEAU

Soit l'instruction suivante :

$titre = "Ceci est <h1>le titre</h1>";

Donnez le code pour afficher la chaîne de ces deux façons :

Ceci est <h1>le titre</h1>
Ceci est le titre

Question 10  NOUVEAU

Écrivez un script qui se contente d'afficher la méthode HTTP (GET ou POST) qui a été utilisée par le client.