Du formulaire HTML au traitement PHP
Voici le flux complet quand un utilisateur soumet un formulaire :
- L'utilisateur remplit le formulaire HTML et clique sur « Envoyer »
- Le navigateur envoie les données au serveur (via GET ou POST)
- PHP récupère les données dans
$_GETou$_POST - PHP traite, valide et répond
<!-- Le formulaire HTML -->
<form action="traitement.php" method="POST">
<label>Votre nom :</label>
<input type="text" name="nom">
<label>Votre email :</label>
<input type="email" name="email">
<button type="submit">Envoyer</button>
</form>
// traitement.php
$nom = $_POST['nom'];
$email = $_POST['email'];
echo "Merci $nom, nous vous contacterons à $email.";
D'abord : les superglobales
Avant de parler de GET et POST, il faut connaître la famille à laquelle ils appartiennent : les superglobales. Ce sont des tableaux que PHP remplit tout seul à chaque requête, et qui sont accessibles partout dans ton code (même à l'intérieur d'une fonction, sans avoir à écrire global). C'est par elles que les données du monde extérieur (le navigateur, le serveur) entrent dans ton programme.
Les principales :
$_GET: les données passées dans l'URL (après le?).$_POST: les données envoyées dans le corps d'une requête POST (formulaires).$_REQUEST: un mélange de$_GET,$_POSTet$_COOKIE. Pratique mais ambigu : mieux vaut viser directement le bon tableau.$_SERVER: des infos sur la requête et le serveur (méthode HTTP, URL, en-têtes, IP du visiteur…).$_SESSION: les données mémorisées entre les pages pour un visiteur (panier, connexion).$_COOKIE: les cookies renvoyés par le navigateur.$_FILES: les fichiers envoyés (upload).$_ENV: les variables d'environnement du serveur.$GLOBALS: toutes les variables globales du script.
On s'en sert comme de n'importe quel tableau associatif : $_POST['email'], $_SERVER['REQUEST_METHOD'], $_SESSION['user']. Pas besoin de les déclarer ni de les importer : elles sont toujours là.
Celles qui transportent des données venues du visiteur ($_GET, $_POST, $_REQUEST, $_COOKIE, $_FILES) ne sont jamais fiables : n'importe qui peut envoyer n'importe quoi. On valide systématiquement à l'entrée et on échappe à l'affichage (on y revient plus bas). À l'inverse, $_SESSION vit côté serveur : elle, on la contrôle.
Les deux que tu croiseras le plus, et de loin, ce sont $_GET et $_POST. Regardons-les de près.
$_GET vs $_POST
Les deux méthodes pour envoyer des données :
- GET : données visibles dans l'URL :
page.php?q=php&page=2 - POST : données invisibles (dans le corps de la requête)
// GET : pour les recherches, filtres, pagination
// URL : recherche.php?q=php&page=2
$recherche = $_GET['q']; // "php"
$page = $_GET['page']; // "2"
// POST : pour les formulaires sensibles (login, contact, paiement)
$email = $_POST['email'];
$password = $_POST['password'];
Règle : utilisez POST pour tout ce qui modifie des données ou contient des informations sensibles. GET uniquement pour lire/rechercher.
Validation des données
Règle d'or : ne jamais faire confiance aux données utilisateur. Un utilisateur (ou un bot) peut envoyer n'importe quoi.
// Vérifier que le champ existe et n'est pas vide
if (empty($_POST['nom'])) {
$erreur = "Le nom est obligatoire.";
}
// Valider un email
$email = $_POST['email'];
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$erreur = "Email invalide.";
}
// Nettoyer les données contre le XSS
$nom = htmlspecialchars($_POST['nom'], ENT_QUOTES, 'UTF-8');
// Transforme <script>alert('hack')</script>
// en <script>alert('hack')</script>
htmlspecialchars() est votre bouclier contre les attaques XSS (Cross-Site Scripting). Utilisez-le chaque fois que vous affichez des données saisies par un utilisateur.
Exemple complet : formulaire de contact
<?php
$erreurs = [];
$succes = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 1. Récupérer et nettoyer
$nom = htmlspecialchars(trim($_POST['nom'] ?? ''), ENT_QUOTES, 'UTF-8');
$email = trim($_POST['email'] ?? '');
$msg = htmlspecialchars(trim($_POST['message'] ?? ''), ENT_QUOTES, 'UTF-8');
// 2. Valider
if (empty($nom)) $erreurs[] = "Le nom est obligatoire.";
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $erreurs[] = "Email invalide.";
if (strlen($msg) < 10) $erreurs[] = "Message trop court (min 10 caractères).";
// 3. Traiter si pas d'erreurs
if (empty($erreurs)) {
// Envoyer un email, sauvegarder en BDD, etc.
$succes = true;
}
}
?>
<?php if ($succes): ?>
<p class="success">Merci <?= $nom ?>, message envoyé !</p>
<?php else: ?>
<?php foreach ($erreurs as $e): ?>
<p class="error"><?= $e ?></p>
<?php endforeach; ?>
<form method="POST">
<input name="nom" value="<?= $nom ?? '' ?>" placeholder="Nom">
<input name="email" value="<?= $email ?? '' ?>" placeholder="Email">
<textarea name="message"><?= $msg ?? '' ?></textarea>
<button>Envoyer</button>
</form>
<?php endif; ?>
Sécurité : ne jamais faire confiance
Résumé des bonnes pratiques :
htmlspecialchars(): contre le XSS, à chaque affichagefilter_var(): pour valider emails, URLs, nombrestrim(): supprimer les espaces parasitesempty(): vérifier qu'un champ n'est pas vide- Requêtes préparées : contre l'injection SQL (leçon 6)
From HTML form to PHP processing
Here's the full flow when a user submits a form:
- The user fills in the HTML form and clicks "Submit"
- The browser sends the data to the server (via GET or POST)
- PHP retrieves the data in
$_GETor$_POST - PHP processes, validates and responds
<!-- The HTML form -->
<form action="process.php" method="POST">
<label>Your name:</label>
<input type="text" name="name">
<label>Your email:</label>
<input type="email" name="email">
<button type="submit">Submit</button>
</form>
// process.php
$name = $_POST['name'];
$email = $_POST['email'];
echo "Thanks $name, we'll contact you at $email.";
First: the superglobals
Before talking about GET and POST, you need to know the family they belong to: the superglobals. These are arrays that PHP fills automatically on every request, and that are accessible everywhere in your code (even inside a function, without writing global). They're how data from the outside world (the browser, the server) enters your program.
The main ones:
$_GET— data passed in the URL (after the?).$_POST— data sent in the body of a POST request (forms).$_REQUEST— a mix of$_GET,$_POSTand$_COOKIE. Handy but ambiguous: better to target the right array directly.$_SERVER— info about the request and the server (HTTP method, URL, headers, visitor IP…).$_SESSION— data remembered across pages for a visitor (cart, login).$_COOKIE— the cookies sent back by the browser.$_FILES— the files uploaded.$_ENV— the server's environment variables.$GLOBALS— all the script's global variables.
You use them like any associative array: $_POST['email'], $_SERVER['REQUEST_METHOD'], $_SESSION['user']. No need to declare or import them: they're always there.
The ones carrying data from the visitor ($_GET, $_POST, $_REQUEST, $_COOKIE, $_FILES) are never trustworthy: anyone can send anything. You validate systematically on the way in and escape on the way out (more below). Conversely, $_SESSION lives on the server: that one you control.
The two you'll meet by far the most are $_GET and $_POST. Let's look at them closely.
$_GET vs $_POST
Two methods to send data:
- GET — data visible in the URL:
page.php?q=php&page=2 - POST — data invisible (in the request body)
// GET — for searches, filters, pagination
// URL: search.php?q=php&page=2
$search = $_GET['q']; // "php"
$page = $_GET['page']; // "2"
// POST — for sensitive forms (login, contact, payment)
$email = $_POST['email'];
$password = $_POST['password'];
Rule: use POST for anything that modifies data or contains sensitive info. GET only for reading/searching.
Data validation
Golden rule: never trust user data. A user (or a bot) can send anything.
// Check that the field exists and isn't empty
if (empty($_POST['name'])) {
$error = "Name is required.";
}
// Validate an email
$email = $_POST['email'];
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error = "Invalid email.";
}
// Sanitize data against XSS
$name = htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF-8');
// Transforms <script>alert('hack')</script>
// into <script>alert('hack')</script>
htmlspecialchars() is your shield against XSS attacks (Cross-Site Scripting). Use it every time you display user-entered data.
Complete example: contact form
<?php
$errors = [];
$success = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 1. Retrieve and sanitize
$name = htmlspecialchars(trim($_POST['name'] ?? ''), ENT_QUOTES, 'UTF-8');
$email = trim($_POST['email'] ?? '');
$msg = htmlspecialchars(trim($_POST['message'] ?? ''), ENT_QUOTES, 'UTF-8');
// 2. Validate
if (empty($name)) $errors[] = "Name is required.";
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = "Invalid email.";
if (strlen($msg) < 10) $errors[] = "Message too short (min 10 characters).";
// 3. Process if no errors
if (empty($errors)) {
// Send email, save to DB, etc.
$success = true;
}
}
?>
<?php if ($success): ?>
<p class="success">Thanks <?= $name ?>, message sent!</p>
<?php else: ?>
<?php foreach ($errors as $e): ?>
<p class="error"><?= $e ?></p>
<?php endforeach; ?>
<form method="POST">
<input name="name" value="<?= $name ?? '' ?>" placeholder="Name">
<input name="email" value="<?= $email ?? '' ?>" placeholder="Email">
<textarea name="message"><?= $msg ?? '' ?></textarea>
<button>Submit</button>
</form>
<?php endif; ?>
Security: never trust input
Summary of best practices:
htmlspecialchars()— against XSS, on every outputfilter_var()— to validate emails, URLs, numberstrim()— remove trailing whitespaceempty()— check that a field is not empty- Prepared statements — against SQL injection (lesson 6)
À vous d'essayer (vrai PHP)
On simule un envoi de formulaire avec un tableau $donnees (comme $_POST), on valide, puis on affiche en sécurisant avec htmlspecialchars. Modifie les données, puis clique sur « Run » :
<?php
// En vrai, ces données viendraient de $_POST. On les simule ici.
$donnees = [
'nom' => 'Alice',
'email' => 'alice@exemple.fr',
];
$erreurs = [];
// Validation
$nom = trim($donnees['nom'] ?? '');
$email = trim($donnees['email'] ?? '');
if ($nom === '') $erreurs[] = "Le nom est obligatoire.";
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $erreurs[] = "Email invalide.";
// Résultat
if ($erreurs) {
foreach ($erreurs as $erreur) {
echo "Erreur : $erreur\n";
}
} else {
echo "Merci $nom ! Message envoyé à $email.\n";
// Et SI on réaffiche un nom dans une PAGE HTML, on l'échappe (anti-XSS).
// htmlspecialchars transforme les balises en texte inoffensif :
$dangereux = 'Bob <script>alert(1)</script>';
echo "\nÉchappé pour le HTML : " . htmlspecialchars($dangereux, ENT_QUOTES, 'UTF-8') . "\n";
}
?>
Copiez ce prompt dans Claude ou ChatGPT :
Crée un formulaire d'inscription PHP complet avec validation : nom, email, mot de passe (min 8 caractères), confirmation du mot de passe. Affiche les erreurs au-dessus du formulaire et pré-remplit les champs en cas d'erreur.
L'IA t'a écrit un formulaire d'inscription avec validation. Sans le relire : pourquoi faut-il valider en PHP côté serveur alors que le navigateur fait déjà des vérifications (required, type="email") ?
curl ou Postman) et viser directement ton traitement.php. Le serveur est le seul endroit que l'attaquant ne contrôle pas : c'est donc le seul endroit où la validation est réelle. filter_var(..., FILTER_VALIDATE_EMAIL) et empty() côté PHP sont la vraie barrière ; le HTML n'est qu'une aide pour l'utilisateur honnête.L'IA te propose ce traitement de recherche. Ton rôle de relecteur : l'accepter tel quel ou le rejeter, et dire pourquoi.
<?php
$q = $_GET['q'];
echo "<h1>Résultats pour : $q</h1>";
?>
$_GET['q'] vient du visiteur et est réaffiché tel quel dans le HTML. Une URL comme ?q=<script>…</script> exécuterait le script dans le navigateur de la victime. Le réflexe pro : échapper à l'affichage avec htmlspecialchars($q, ENT_QUOTES, 'UTF-8'), et au passage gérer le cas où q n'existe pas ($_GET['q'] ?? '') pour éviter le warning. Le code « marche » sur un test gentil, mais il est exploitable : c'est exactement le genre de ligne qu'il ne faut jamais laisser passer.Sans remonter dans la leçon : quand choisis-tu $_POST plutôt que $_GET, et à quoi sert htmlspecialchars() ?
$_GET met les données dans l'URL (recherches, filtres, pagination : rien de sensible, c'est partageable et mis en cache). $_POST les met dans le corps de la requête : on l'utilise dès qu'on modifie des données ou qu'il y a du sensible (login, contact, paiement). htmlspecialchars() transforme les caractères HTML (<, >, ", &) en entités : c'est le bouclier anti-XSS, à appliquer à chaque fois qu'on réaffiche une donnée venue de l'utilisateur.$_GET pour l'URL page.php?id=42 ?A form captures data fine, but PHP forgets it the moment the next page loads. So how do you keep a visitor logged in from page to page? Off to sessions and cookies, the memory that survives a reload.
Lesson 5: Sessions and cookies →