Objectifs de cette leçon
- Récupérer les données POST et GET
- Valider les entrées utilisateur
- Sécuriser l'affichage avec htmlspecialchars
Formulaires HTML et PHP 📝
Les formulaires sont le pont entre l'utilisateur et le serveur. PHP excelle pour traiter les données de formulaires de manière sécurisée.
Structure de base d'un formulaire
<!-- index.php --> <form method="POST" action="traitement.php"> <label for="nom">Nom :</label> <input type="text" id="nom" name="nom" required> <label for="email">Email :</label> <input type="email" id="email" name="email" required> <label for="message">Message :</label> <textarea id="message" name="message" required></textarea> <button type="submit">Envoyer</button> </form>
💡 Règle d'or : L'attribut
nameest CE QUI ENVOIE les données au serveur. Sansname, la donnée n'est pas transmise.
Récupération des données
<?php // traitement.php // Vérifier si le formulaire a été soumis if ($_SERVER["REQUEST_METHOD"] === "POST") { // Récupérer les données (avec ?? pour éviter les erreurs) $nom = $_POST["nom"] ?? ""; $email = $_POST["email"] ?? ""; $message = $_POST["message"] ?? ""; // Validation de base if (empty($nom) || empty($email) || empty($message)) { echo "Tous les champs sont obligatoires."; exit; } // Afficher les données reçues echo "Nom : " . htmlspecialchars($nom) . "\n"; echo "Email : " . htmlspecialchars($email) . "\n"; echo "Message : " . htmlspecialchars($message) . "\n"; } ?>
Types de champs de formulaire
<?php // Champ texte <input type="text" name="prenom" value="<?= $_GET['prenom'] ?? '' ?>"> // Email avec validation HTML5 <input type="email" name="email" required> // Mot de passe <input type="password" name="mdp" minlength="8" required> // Nombre <input type="number" name="age" min="0" max="120" step="1"> // Date <input type="date" name="naissance"> // Sélection (dropdown) <select name="pays"> <option value="">-- Choisir --</option> <option value="FR">France</option> <option value="BE">Belgique</option> <option value="CH">Suisse</option> </select> // Boutons radio <input type="radio" name="genre" value="H" id="h"> <label for="h">Homme</label> <input type="radio" name="genre" value="F" id="f"> <label for="f">Femme</label> // Cases à cocher <input type="checkbox" name="conditions" value="accepte" id="c"> <label for="c">J'accepte les conditions</label> // Textarea <textarea name="commentaire" rows="5" cols="40"></textarea> // Fichier <input type="file" name="avatar" accept="image/*"> ?>
Sécurité — Les 3 règles d'or
<?php // 1. TOUJOURS valider les données côté serveur $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); if (!$email) { die("Email invalide"); } // 2. TOUJOURS échapper la sortie (protection XSS) echo htmlspecialchars($donneeUtilisateur, ENT_QUOTES, 'UTF-8'); // 3. TOUJOURS utiliser des requêtes préparées pour la base de données $stmt = $pdo->prepare("INSERT INTO messages (nom, email, message) VALUES (?, ?, ?)"); $stmt->execute([$nom, $email, $message]); ?>
⚠️ XSS : Si tu affiches du contenu utilisateur sans
htmlspecialchars(), quelqu'un peut injecter du JavaScript malveillant dans ta page.
Protection CSRF
<?php session_start(); // Générer un token CSRF if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } // Dans le formulaire HTML : // <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>"> // Vérifier le token à la réception if ($_SERVER["REQUEST_METHOD"] === "POST") { if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) { die("Token CSRF invalide — tentative d'attaque ?"); } // Traitement... } ?>
Traitement d'un formulaire complet
<?php // contact.php — formulaire complet sécurisé session_start(); // Générer le token if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } $erreurs = []; $succes = false; if ($_SERVER["REQUEST_METHOD"] === "POST") { // Vérifier CSRF if ($_POST['csrf_token'] ?? '' !== $_SESSION['csrf_token']) { die("Token invalide"); } // Récupérer et nettoyer $nom = trim($_POST['nom'] ?? ''); $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); $sujet = trim($_POST['sujet'] ?? ''); $message = trim($_POST['message'] ?? ''); // Valider if (empty($nom)) $erreurs[] = "Le nom est requis"; if (!$email) $erreurs[] = "L'email est invalide"; if (empty($sujet)) $erreurs[] = "Le sujet est requis"; if (strlen($message) < 10) $erreurs[] = "Le message doit faire 10 caractères minimum"; // Si pas d'erreurs, traiter if (empty($erreurs)) { // Envoyer l'email $destinataire = "contact@monsite.com"; $headers = "From: $email\r\n"; $headers .= "Reply-To: $email\r\n"; $headers .= "Content-Type: text/plain; charset=UTF-8\r\n"; mail($destinataire, $sujet, $message, $headers); $succes = true; // Regénérer le token $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } } ?>
Réception de fichier upload
<?php if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_FILES['avatar'])) { $fichier = $_FILES['avatar']; // Vérifier les erreurs if ($fichier['error'] !== UPLOAD_ERR_OK) { die("Erreur upload : " . $fichier['error']); } // Vérifier la taille (max 5 Mo) if ($fichier['size'] > 5 * 1024 * 1024) { die("Fichier trop volumineux (max 5 Mo)"); } // Vérifier le type MIME $typesPermis = ['image/jpeg', 'image/png', 'image/gif']; $typeMime = mime_content_type($fichier['tmp_name']); if (!in_array($typeMime, $typesPermis)) { die("Type de fichier non autorisé"); } // Déplacer le fichier $dossier = "uploads/"; $nomFichier = uniqid() . "_" . basename($fichier['name']); move_uploaded_file($fichier['tmp_name'], $dossier . $nomFichier); echo "Fichier uploadé avec succès !"; } ?>
Comparaison avec JavaScript (fetch API)
| Aspect | JavaScript | PHP |
|---|---|---|
| Soumission | fetch() ou XMLHttpRequest | Formulaire HTML classique |
| Validation | Côté client (JS) | Côté serveur (PHP) |
| Sécurité | JS désactivable | Incontournable côté serveur |
| Feedback | Asynchrone | Synchrone (rechargement) |
💡 Astuce : Utilise JavaScript pour la validation instantanée côté client (meilleure UX), mais TOUJOURS valider à nouveau côté serveur avec PHP.
Exercice pratique
Crée un formulaire d'inscription sécurisé avec :
- Champs : nom, email, mot de passe, confirmation
- Validation complète côté serveur
- Protection CSRF
- Affichage des erreurs
- Message de succès
<?php session_start(); $csrf = bin2hex(random_bytes(32)); $_SESSION['csrf_token'] = $csrf; $erreurs = []; if ($_SERVER["REQUEST_METHOD"] === "POST") { $nom = trim($_POST['nom'] ?? ''); $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); $mdp = $_POST['mdp'] ?? ''; $mdp2 = $_POST['mdp2'] ?? ''; if (empty($nom)) $erreurs[] = "Nom requis"; if (!$email) $erreurs[] = "Email invalide"; if (strlen($mdp) < 8) $erreurs[] = "Mot de passe trop court (8 min)"; if ($mdp !== $mdp2) $erreurs[] = "Les mots de passe ne correspondent pas"; if (empty($erreurs)) { $hash = password_hash($mdp, PASSWORD_DEFAULT); echo "Inscription réussie pour $nom !"; } } ?>
🎯 A retenir : Sécurité d'abord — validation serveur, échappement de sortie, tokens CSRF, et requêtes préparées. Ne JAMAIS faire confiance aux données du client.
Prochaine leçon : Sessions et cookies en PHP — garde l'utilisateur connecté !
⚡ Simulateur — Formulaires PHP
Étape 1/6Ouverture du bloc PHP pour traiter le formulaire.