Validation de formulaire PHP
La validation de formulaire est essentielle au développement web. Découvrez comment valider et sécuriser les données soumises par les utilisateurs en PHP.
La validation de formulaire est le processus qui consiste à vérifier que les données soumises par un utilisateur via un formulaire HTML sont présentes, correctement formatées et sûres à utiliser avant que votre script ne les traite. En PHP, la validation s'exécute côté serveur après la soumission du formulaire, et ne peut donc pas être contournée en désactivant JavaScript ou en envoyant directement une requête.
Ce chapitre couvre l'intégralité du workflow de validation : pourquoi la validation côté serveur est importante, la différence entre nettoyer et valider, les fonctions PHP à utiliser, ainsi qu'un exemple complet et sécurisé que vous pouvez adapter. Si vous débutez avec la réception de saisies de formulaire, lisez d'abord Traitement des formulaires PHP.
Pourquoi la validation côté serveur est importante
La validation côté client (HTML5 required, type="email", JavaScript) améliore l'expérience utilisateur en détectant les erreurs instantanément — mais c'est uniquement un agrément. Un utilisateur déterminé ou malveillant peut désactiver JavaScript ou envoyer une requête HTTP construite qui contourne entièrement le navigateur. Le serveur est le seul endroit où la validation peut être fiable. La validation PHP côté serveur vous permet de :
- Garantir que les champs obligatoires sont bien présents et non vides.
- Confirmer que les valeurs correspondent au format attendu (un vrai e-mail, un nombre dans la bonne plage).
- Neutraliser les saisies dangereuses avant qu'elles n'atteignent une base de données ou une page HTML, prévenant ainsi l'injection SQL et le cross-site scripting (XSS).
Traitez chaque valeur de $_POST, $_GET et $_REQUEST comme non fiable jusqu'à ce que vous l'ayez vérifiée. Ces tableaux proviennent des superglobales PHP.
Nettoyer vs. Valider
Ces deux termes sont souvent confondus, mais ils font des choses différentes :
- Nettoyer épure une valeur — cela supprime ou échappe les caractères indésirables.
trim()supprime les espaces en début et fin de chaîne ;htmlspecialchars()convertit<,>,&et les guillemets en entités HTML afin qu'ils s'affichent comme du texte au lieu de s'exécuter. - Valider vérifie une valeur par rapport à une règle et indique si elle est valide ou non — cela ne modifie pas la valeur.
filter_var($email, FILTER_VALIDATE_EMAIL)retourne l'e-mail s'il semble valide, oufalsedans le cas contraire.
Un flux typique est : nettoyer d'abord (supprimer les espaces), puis valider, et enfin échapper lors de la sortie (lorsqu'on affiche du contenu HTML). Pour une couverture approfondie du système de filtrage PHP, voir PHP Filters et filter_var().
Étapes de validation
Une routine de validation côté serveur suit généralement les mêmes quatre étapes :
- Créer le formulaire HTML et pointer son
actionvers le script PHP. - Détecter une soumission
POSTavec$_SERVER["REQUEST_METHOD"]. - Pour chaque champ : lire la valeur, la nettoyer, puis la valider — en collectant les messages d'erreur.
- Si tous les champs sont valides, traiter les données ; sinon ré-afficher le formulaire avec les messages d'erreur et les valeurs déjà saisies par l'utilisateur.
Fonctions PHP de validation utiles
| Fonction | Objectif |
|---|---|
trim() | Supprime les espaces en début et fin d'une chaîne. |
empty() | Vérifie si une valeur est absente ou une chaîne vide. |
filter_var() | Valide ou nettoie en utilisant un filtre intégré (par ex. FILTER_VALIDATE_EMAIL, FILTER_VALIDATE_INT). |
is_numeric() | Retourne true si la valeur est un nombre ou une chaîne numérique. |
htmlspecialchars() | Échappe les caractères spéciaux HTML pour prévenir le XSS à la sortie. |
preg_match() | Valide selon un modèle d'expression régulière personnalisé. |
Un exemple minimal
Avant l'exemple complet avec base de données ci-dessous, voici la validation la plus simple qui capture le schéma de base — nettoyer, puis valider, puis collecter les erreurs :
<?php
$email = trim($_POST["email"] ?? "");
$errors = [];
if ($email === "") {
$errors["email"] = "Please enter your email.";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors["email"] = "Please enter a valid email address.";
}
if (empty($errors)) {
echo "Valid email: " . htmlspecialchars($email);
} else {
echo $errors["email"];
}
?>Si $_POST["email"] vaut " [email protected] ", les espaces environnants sont supprimés, la valeur est validée et le script affiche Valid email: [email protected]. Une saisie comme "not-an-email" produit Please enter a valid email address.
Exemple complet : validation et enregistrement d'un formulaire
L'exemple ci-dessous valide un nom, un e-mail, un genre et un commentaire, puis insère la ligne en utilisant une requête préparée — l'approche avec requêtes préparées (via mysqli) est ce qui vous protège de l'injection SQL, car les saisies utilisateur sont envoyées séparément du texte SQL et ne sont jamais interprétées comme du code.
Mettez à jour les identifiants de base de données et assurez-vous que votre base de données contient une table users avec les colonnes name, email, gender et comment avant d'exécuter cet exemple.
<?php
// Database connection setup
$link = mysqli_connect("localhost", "username", "password", "database");
if (!$link) {
die("Connection failed: " . mysqli_connect_error());
}
// Define variables and initialize with empty values
$name = $email = $gender = $comment = $website = "";
$name_err = $email_err = $gender_err = $comment_err = "";
// Processing form data when form is submitted
if($_SERVER["REQUEST_METHOD"] == "POST"){
// Validate name
if(empty(trim($_POST["name"] ?? ""))){
$name_err = "Please enter your name.";
} else{
$name = trim($_POST["name"]);
}
// Validate email
if(empty(trim($_POST["email"] ?? ""))){
$email_err = "Please enter your email.";
} elseif(!filter_var(trim($_POST["email"] ?? ""), FILTER_VALIDATE_EMAIL)) {
$email_err = "Please enter a valid email address.";
} else{
$email = trim($_POST["email"]);
}
// Validate gender
if(!isset($_POST["gender"]) || empty($_POST["gender"])){
$gender_err = "Please select your gender.";
} else{
$gender = $_POST["gender"];
}
// Validate comment
if(empty(trim($_POST["comment"] ?? ""))){
$comment_err = "Please enter your comment.";
} else{
$comment = trim($_POST["comment"]);
}
// Check input errors before inserting in database
if(empty($name_err) && empty($email_err) && empty($gender_err) && empty($comment_err)){
// Prepare an insert statement
$sql = "INSERT INTO users (name, email, gender, comment) VALUES (?, ?, ?, ?)";
if($stmt = mysqli_prepare($link, $sql)){
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "ssss", $param_name, $param_email, $param_gender, $param_comment);
// Set parameters
$param_name = $name;
$param_email = $email;
$param_gender = $gender;
$param_comment = $comment;
// Attempt to execute the prepared statement
if(mysqli_stmt_execute($stmt)){
// Records created successfully. Redirect to landing page
header("location: index.php");
exit();
} else{
echo "Something went wrong. Please try again later.";
}
}
// Close statement
mysqli_stmt_close($stmt);
}
}
// Close connection
mysqli_close($link);
?>
<!DOCTYPE html>
<html>
<head><title>PHP Form Validation</title></head>
<body>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
Name: <input type="text" name="name" value="<?php echo htmlspecialchars($name); ?>">
<span class="error"><?php echo $name_err; ?></span><br><br>
Email: <input type="text" name="email" value="<?php echo htmlspecialchars($email); ?>">
<span class="error"><?php echo $email_err; ?></span><br><br>
Gender:
<input type="radio" name="gender" value="female"> Female
<input type="radio" name="gender" value="male"> Male
<span class="error"><?php echo $gender_err; ?></span><br><br>
Comment: <textarea name="comment"><?php echo htmlspecialchars($comment); ?></textarea>
<span class="error"><?php echo $comment_err; ?></span><br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>Afficher les erreurs et conserver la saisie de l'utilisateur
Trois détails dans l'exemple méritent attention pour une bonne expérience utilisateur :
- Chaque variable d'erreur (
$name_err,$email_err, …) est affichée dans un<span class="error">à côté de son champ, afin que l'utilisateur sache exactement quel champ corriger. - L'attribut
actiondu formulaire affichehtmlspecialchars($_SERVER["PHP_SELF"]). Sans échappement,PHP_SELFpeut être exploité pour injecter du script via l'URL, donc l'échapper est une mesure de sécurité, pas seulement une question de formatage. - Chaque valeur ré-affichée dans le formulaire est passée par
htmlspecialchars(). Cela prévient à la fois le XSS et permet à l'utilisateur de conserver ce qu'il a déjà saisi au lieu de tout ressaisir après un champ invalide.
Pièges courants
empty()traite"0"comme vide. Un champ dont la valeur est la chaîne"0"échouera à une vérificationempty(). Pour les champs où0est une valeur valide, comparez explicitement :if ($value === "").- Validez avant de faire confiance au type. Les valeurs de
$_POSTsont toujours des chaînes. Utilisezfilter_var($n, FILTER_VALIDATE_INT)ouis_numeric()plutôt que de supposer qu'un nombre est arrivé. - Échappez à la sortie, pas au stockage. Stockez la valeur brute (validée) dans la base de données et appliquez
htmlspecialchars()uniquement lors de l'affichage en HTML. Échapper avant le stockage corrompt les données pour les usages non-HTML. - Utilisez l'opérateur de coalescence null.
$_POST["x"] ?? ""évite les avertissements "Undefined array key" lorsqu'un champ est absent.
Valider d'autres types de champs
Le même schéma s'applique à tout champ — seule la règle de validation change :
<?php
// Age: an integer between 18 and 120
$age = filter_var($_POST["age"] ?? "", FILTER_VALIDATE_INT, [
"options" => ["min_range" => 18, "max_range" => 120],
]);
if ($age === false) {
echo "Please enter an age between 18 and 120.";
}
// Username: 3-16 letters, digits, or underscores
$username = trim($_POST["username"] ?? "");
if (!preg_match('/^[A-Za-z0-9_]{3,16}$/', $username)) {
echo "Username must be 3-16 letters, digits, or underscores.";
}
?>Pour les règles spécifiques aux URL et aux e-mails, voir Formulaire PHP URL & E-mail ; pour marquer des champs comme obligatoires, voir Champs obligatoires du formulaire PHP ; et pour voir toutes les pièces assemblées, voir Formulaire PHP complet.
Conclusion
La validation côté serveur en PHP est ce qui rend un formulaire fiable : elle confirme que les données sont présentes et correctement formatées, et — combinée à htmlspecialchars() en sortie et aux requêtes préparées pour le stockage — elle bloque le XSS et l'injection SQL. La recette de base est toujours la même : nettoyer, valider, collecter les erreurs et ré-afficher le formulaire avec des messages utiles en cas de problème. Maîtrisez cette boucle et vous pourrez valider n'importe quel champ en changeant simplement la règle.