Aller au contenu

Formulaires et validation

Jusqu’ici, les pages produisaient du contenu. Avec les formulaires, le visiteur envoie à son tour des données au serveur : un message de contact, une recherche, une inscription. Ce chapitre suit ce trajet de bout en bout : envoyer, récupérer, valider, puis afficher sans danger.

Rappel : méthodes HTTP et communication client-serveur

Section intitulée « Rappel : méthodes HTTP et communication client-serveur »

Chaque requête HTTP porte une méthode qui annonce l’intention du client. Deux nous occupent ici :

  • GET demande une ressource (lire une page, une recherche).
  • POST envoie des données au serveur pour qu’il les traite (un message, une création).

Soumettre un formulaire, c’est donc déclencher une nouvelle requête, exactement le cycle vu au chapitre Introduction, mais cette fois la requête transporte les données saisies.

  1. Client (navigateur) vers Serveur (Apache + PHP) : Requête POST (POST /contact.php (+ données))
  2. Serveur (Apache + PHP) : Récupère et valide les données
  3. Serveur (Apache + PHP) vers Client (navigateur) : 200 · Réponse : HTML (confirmation ou erreurs)
L'envoi d'un formulaire, du navigateur à la réponse

Côté navigateur, c’est la balise <form> qui prépare l’envoi. Deux attributs comptent : action (l’URL qui recevra la requête) et method (get ou post).

<form action="contact.php" method="post">
<label>Nom <input type="text" name="nom"></label>
<label>Courriel <input type="email" name="courriel"></label>
<label>Message <textarea name="message"></textarea></label>
<button type="submit">Envoyer</button>
</form>

L’attribut name de chaque champ est essentiel : c’est lui qui devient la clé sous laquelle PHP retrouvera la valeur. Un champ sans name n’est jamais transmis.

La méthode change l’endroit où voyagent les données :

  • Avec GET, elles partent dans l’URL, à la suite d’un ? : produits.php?q=sirop. Visibles, partageables, mais limitées en taille — parfait pour une recherche ou un filtre.
  • Avec POST, elles partent dans le corps de la requête, hors de l’URL — adapté à l’envoi d’un message, d’un mot de passe, d’un fichier.
<!-- Une recherche : GET, car on ne fait que lire -->
<form action="produits.php" method="get">
<input type="search" name="q" placeholder="Rechercher un produit">
<button type="submit">Chercher</button>
</form>

Côté serveur, PHP dépose les données reçues dans deux superglobales, des tableaux associatifs accessibles partout : $_GET pour les données d’URL, $_POST pour celles du corps. La clé est le name du champ.

<?php
$nom = $_POST["nom"] ?? "";
$courriel = $_POST["courriel"] ?? "";
$message = $_POST["message"] ?? "";

On distingue souvent le premier affichage du formulaire de son traitement en testant la méthode de la requête :

<?php
if ($_SERVER["REQUEST_METHOD"] === "POST") {
// Le formulaire a été soumis : on récupère et on traite.
$nom = $_POST["nom"] ?? "";
}

Une donnée qui arrive du client n’est jamais fiable : un champ peut être vide, mal rempli, ou trafiqué en contournant le navigateur. Toute validation qui compte doit se faire côté serveur. La validation HTML (required, type="email") améliore le confort, mais se désactive en deux clics : elle ne protège rien.

La démarche habituelle : rassembler les erreurs dans un tableau, puis ne traiter que si ce tableau est vide.

<?php
$erreurs = [];
$nom = trim($_POST["nom"] ?? "");
$courriel = trim($_POST["courriel"] ?? "");
$message = trim($_POST["message"] ?? "");
if ($nom === "") {
$erreurs[] = "Le nom est obligatoire.";
}
if (!filter_var($courriel, FILTER_VALIDATE_EMAIL)) {
$erreurs[] = "Le courriel n'est pas valide.";
}
if (mb_strlen($message) < 10) {
$erreurs[] = "Le message doit contenir au moins 10 caractères.";
}
if (empty($erreurs)) {
// Les données sont valides : on les enregistre, on envoie le courriel, etc.
echo "Merci, votre message a bien été reçu.";
}

Quand des erreurs existent, on réaffiche le formulaire avec les messages — et en conservant ce que la personne avait déjà saisi, pour ne pas la forcer à tout retaper.

  1. Si le tableau $erreurs n’est pas vide, on les liste au-dessus du formulaire :

    <?php foreach ($erreurs as $erreur): ?>
    <p class="erreur"><?php echo htmlspecialchars($erreur); ?></p>
    <?php endforeach; ?>
  2. On repré-remplit chaque champ avec la valeur reçue, échappée :

    <input type="text" name="nom"
    value="<?php echo htmlspecialchars($nom); ?>">

Un formulaire n’est qu’une façon, parmi d’autres, d’envoyer des données. Une API reçoit des requêtes émises non par un navigateur, mais par un autre programme (application mobile, autre serveur, code JavaScript). Le principe reste le même — une requête, une méthode, une réponse — mais les données échangées sont généralement du JSON plutôt que du HTML.

<?php
// Au lieu de renvoyer du HTML, on renvoie du JSON.
header("Content-Type: application/json");
echo json_encode(["statut" => "ok", "message" => "Reçu"]);
<?php
// Et on lit un corps JSON envoyé par le client (au lieu de $_POST).
$donnees = json_decode(file_get_contents("php://input"), true);
Quelle que soit la porte d’entrée — formulaire ou API — les données viennent de l’extérieur : on les valide toujours avant de leur faire confiance.

La validation protège l’entrée. Il reste à protéger la sortie. Afficher tel quel un texte fourni par l’utilisateur ouvre la porte à une attaque par injection : si quelqu’un saisit comme nom une balise <script>, elle s’exécutera dans le navigateur de tous ceux qui verront la page. C’est une faille XSS (cross-site scripting).

<?php
// DANGEREUX : la saisie est insérée telle quelle dans la page.
echo "Bonjour " . $_GET["nom"];

La parade est systématique : htmlspecialchars() convertit les caractères dangereux (<, >, &, ") en entités HTML inoffensives. La balise s’affiche alors comme du texte, sans s’exécuter.

<?php
// SÛR : la saisie est échappée avant l'affichage.
echo "Bonjour " . htmlspecialchars($_GET["nom"]);

Échappez avec htmlspecialchars() tout ce qui provient de l’utilisateur, au moment de l’afficher — dans le corps de la page comme dans les attributs (value="..."). C’est le même réflexe que pour les fragments réutilisés, vu au chapitre Navigation et composition.

Vérification Pourquoi valider côté serveur si le formulaire a déjà des attributs required et type='email' ?

Parce que la validation HTML s’exécute dans le navigateur, où elle peut être désactivée ou contournée (en envoyant la requête directement, sans passer par le formulaire). Le serveur est le seul endroit que le client ne contrôle pas : c’est là que la validation doit avoir lieu pour de bon.

  • Soumettre un formulaire déclenche une requête HTTP : GET pour lire (données dans l’URL), POST pour envoyer (données dans le corps).
  • L’attribut name de chaque champ devient la clé dans $_GET ou $_POST ; ?? gère l’absence de valeur.
  • La validation côté serveur est la seule qui compte : rassemblez les erreurs, ne traitez que si elles sont absentes, et réaffichez la saisie en cas d’échec.
  • Une API reçoit les mêmes requêtes en JSON : même discipline de validation.
  • À l’affichage, htmlspecialchars() sur toute donnée venue de l’utilisateur évite les failles XSS.

Quiz. Quelle méthode pour envoyer un message de contact à enregistrer ?

Quiz. Sous quelle clé PHP retrouve-t-il la valeur de <input name='courriel'> envoyé en POST ?

Quiz. À quoi sert htmlspecialchars() ?

Quiz. Pourquoi ne pas se fier à la validation HTML (required, type='email') seule ?