Formation DWWM - Collecte et validation de données
2025 - 2026
Pourquoi et comment ?
C'est le conteneur principal de tous les éléments du formulaire
<form action="traitement.php" method="POST">
<!-- Tous les champs du formulaire ici -->
</form>
| Critère | GET | POST |
|---|---|---|
| Visibilité | Données dans l'URL | Données cachées |
| Sécurité | ❌ Faible | ✅ Meilleure |
| Taille limite | ~2000 caractères | Illimitée |
| Mise en cache | ✅ Oui | ❌ Non |
Input et Label
<input type="text" name="prenom" id="prenom">
<!-- Méthode 1 : avec l'attribut for -->
<label for="prenom">Prénom :</label>
<input type="text" id="prenom" name="prenom">
<!-- Méthode 2 : imbrication -->
<label>
Prénom :
<input type="text" name="prenom">
</label>
<form action="inscription.php" method="POST">
<div>
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom" required>
</div>
<div>
<label for="email">Email :</label>
<input type="email" id="email" name="email" required>
</div>
<button type="submit">S'inscrire</button>
</form>
Une richesse de possibilités
Le champ texte classique pour texte court
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom"
placeholder="Entrez votre nom"
maxlength="50">
Validation automatique du format email
<label for="email">Email :</label>
<input type="email" id="email" name="email"
placeholder="exemple@email.com"
required>
Masque automatiquement les caractères saisis
<label for="password">Mot de passe :</label>
<input type="password" id="password" name="password"
minlength="8"
required>
Pour les valeurs numériques uniquement
<label for="age">Âge :</label>
<input type="number" id="age" name="age"
min="18"
max="120"
step="1">
Sélecteur de date intégré au navigateur
<label for="naissance">Date de naissance :</label>
<input type="date" id="naissance" name="naissance"
min="1900-01-01"
max="2024-12-31">
Sélecteur d'heure
<label for="heure">Heure de rendez-vous :</label>
<input type="time" id="heure" name="heure"
min="09:00"
max="18:00">
Pour les numéros de téléphone (affiche clavier numérique sur mobile)
<label for="tel">Téléphone :</label>
<input type="tel" id="tel" name="tel"
pattern="[0-9]{10}"
placeholder="0612345678">
Validation automatique du format URL
<label for="site">Site web :</label>
<input type="url" id="site" name="site"
placeholder="https://example.com">
Sélecteur de couleur intégré
<label for="couleur">Couleur préférée :</label>
<input type="color" id="couleur" name="couleur"
value="#42affa">
Curseur pour sélectionner une valeur dans une plage
<label for="volume">Volume :</label>
<input type="range" id="volume" name="volume"
min="0" max="100" value="50" step="10">
Pour télécharger des fichiers
<label for="cv">CV (PDF uniquement) :</label>
<input type="file" id="cv" name="cv"
accept=".pdf"
required>
<!-- Fichiers multiples -->
<input type="file" name="photos"
accept="image/*"
multiple>
enctype="multipart/form-data" sur le <form>
Cases à cocher (sélection multiple)
<label>
<input type="checkbox" name="newsletter" value="oui">
Je souhaite recevoir la newsletter
</label>
<!-- Groupe de checkboxes -->
<p>Langages maîtrisés :</p>
<label>
<input type="checkbox" name="langages[]" value="html"> HTML
</label>
<label>
<input type="checkbox" name="langages[]" value="css"> CSS
</label>
<label>
<input type="checkbox" name="langages[]" value="js"> JavaScript
</label>
Boutons radio (un seul choix parmi plusieurs)
<p>Civilité :</p>
<label>
<input type="radio" name="civilite" value="mr" checked> M.
</label>
<label>
<input type="radio" name="civilite" value="mme"> Mme
</label>
<label>
<input type="radio" name="civilite" value="autre"> Autre
</label>
name
Champ caché (non visible par l'utilisateur)
<input type="hidden" name="user_id" value="12345">
<input type="hidden" name="token" value="abc123xyz">
| Type | Usage |
|---|---|
| text | Texte court |
| Email (validation auto) | |
| password | Mot de passe masqué |
| number | Valeur numérique |
| date/time | Date et heure |
| tel/url | Téléphone et URL |
| checkbox/radio | Sélection |
| file | Upload fichier |
Textarea, Select, Button
Pour les textes longs (commentaires, descriptions...)
<label for="message">Votre message :</label>
<textarea id="message" name="message"
rows="5"
cols="40"
placeholder="Écrivez votre message ici..."
maxlength="500"></textarea>
Menu déroulant pour sélectionner une option
<label for="pays">Pays :</label>
<select id="pays" name="pays" required>
<option value="">-- Sélectionnez un pays --</option>
<option value="fr">France</option>
<option value="be">Belgique</option>
<option value="ch">Suisse</option>
<option value="ca">Canada</option>
</select>
Regrouper les options par catégories
<label for="ville">Ville :</label>
<select id="ville" name="ville">
<optgroup label="Île-de-France">
<option value="paris">Paris</option>
<option value="versailles">Versailles</option>
</optgroup>
<optgroup label="Provence">
<option value="marseille">Marseille</option>
<option value="nice">Nice</option>
</optgroup>
</select>
<label for="competences">Compétences :</label>
<select id="competences" name="competences[]" multiple size="5">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
<option value="php">PHP</option>
<option value="sql">SQL</option>
</select>
<!-- Bouton de soumission -->
<button type="submit">Envoyer</button>
<!-- Bouton de réinitialisation -->
<button type="reset">Réinitialiser</button>
<!-- Bouton neutre (nécessite JavaScript) -->
<button type="button" onclick="maFonction()">Action</button>
<!-- Ancienne méthode -->
<input type="submit" value="Envoyer">
<!-- Méthode moderne (recommandée) -->
<button type="submit">
✉️ Envoyer le message
</button>
Regrouper des champs liés visuellement et sémantiquement
<fieldset>
<legend>Informations personnelles</legend>
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom">
<label for="prenom">Prénom :</label>
<input type="text" id="prenom" name="prenom">
</fieldset>
<fieldset>
<legend>Coordonnées</legend>
<label for="email">Email :</label>
<input type="email" id="email" name="email">
</fieldset>
Suggestions tout en permettant la saisie libre
<label for="navigateur">Navigateur préféré :</label>
<input type="text" id="navigateur" name="navigateur"
list="navigateurs">
<datalist id="navigateurs">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
</datalist>
Contrôler les données avant envoi
Rend un champ obligatoire
<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>
<button type="submit">Envoyer</button>
Validation avec expression régulière (regex)
<!-- Code postal français (5 chiffres) -->
<input type="text" name="code_postal"
pattern="[0-9]{5}"
title="5 chiffres requis">
<!-- Téléphone français -->
<input type="tel" name="telephone"
pattern="0[1-9][0-9]{8}"
title="Format : 0612345678">
| Pattern | Description |
|---|---|
| [0-9]{5} | 5 chiffres (code postal) |
| [A-Za-z]+ | Lettres uniquement |
| [A-Za-z0-9]{6,12} | Alphanumérique 6-12 car. |
| 0[1-9][0-9]{8} | Téléphone français |
| [A-Z]{2}[0-9]{3} | 2 lettres + 3 chiffres |
<!-- Longueur de texte -->
<input type="text" name="username"
minlength="3" maxlength="20">
<!-- Valeurs numériques -->
<input type="number" name="age"
min="18" max="120">
<!-- Dates -->
<input type="date" name="date"
min="1900-01-01" max="2024-12-31">
Définit l'incrément pour les champs numériques
<!-- Nombres entiers -->
<input type="number" name="quantite"
min="1" max="100" step="1">
<!-- Décimales (prix) -->
<input type="number" name="prix"
min="0" step="0.01">
<!-- Multiples de 5 -->
<input type="number" name="age"
min="18" step="5">
<!-- Sur le formulaire entier -->
<form action="traitement.php" method="POST" novalidate>
<!-- Tous les champs ici -->
</form>
<!-- Sur un bouton de soumission spécifique -->
<button type="submit" formnovalidate>
Enregistrer le brouillon
</button>
Avec JavaScript (setCustomValidity)
<form id="monForm">
<input type="password" id="pass1" required>
<input type="password" id="pass2" required>
<button type="submit">Valider</button>
</form>
<script>
const pass2 = document.getElementById('pass2');
pass2.addEventListener('input', function() {
if (pass2.value !== document.getElementById('pass1').value) {
pass2.setCustomValidity('Les mots de passe ne correspondent pas');
} else {
pass2.setCustomValidity('');
}
});
</script>
Des formulaires pour tous
<input type="text" name="nom" placeholder="Nom">
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom">
Pourquoi ? Les lecteurs d'écran annoncent le label associé
Quand un label visuel n'est pas possible
<!-- Bouton de recherche avec icône uniquement -->
<button type="submit" aria-label="Rechercher">
🔍
</button>
<!-- Champ avec icône mais sans texte -->
<input type="search"
name="recherche"
aria-label="Rechercher sur le site"
placeholder="Recherche...">
<fieldset>
<legend>Civilité</legend>
<label><input type="radio" name="civilite" value="mr"> M.</label>
<label><input type="radio" name="civilite" value="mme"> Mme</label>
</fieldset>
<fieldset>
<legend>Compétences</legend>
<label><input type="checkbox" name="comp[]" value="html"> HTML</label>
<label><input type="checkbox" name="comp[]" value="css"> CSS</label>
</fieldset>
Pourquoi ? Le lecteur d'écran annonce : "Civilité, groupe, M., bouton radio"
<label for="email">Email :</label>
<input type="email"
id="email"
name="email"
aria-describedby="email-error"
aria-invalid="true">
<p id="email-error" class="error" role="alert">
⚠️ Veuillez entrer une adresse email valide
</p>
/* Ceci rend la navigation impossible ! */
*:focus { outline: none; }
<!-- tabindex="0" : ordre naturel -->
<div tabindex="0">Élément focusable</div>
<!-- tabindex="-1" : non dans l'ordre, mais focusable en JS -->
<div tabindex="-1">Pas dans la navigation</div>
<!-- tabindex > 0 : À ÉVITER (anti-pattern) -->
<input tabindex="1"> <!-- ❌ Ne pas utiliser -->
<label for="nom">
Nom <span class="required" aria-label="obligatoire">*</span>
</label>
<input type="text"
id="nom"
name="nom"
required
aria-required="true">
Créer des formulaires professionnels
<form action="traitement.php" method="POST">
<!-- Groupe 1 -->
<div class="form-group">
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom" required>
</div>
<!-- Groupe 2 -->
<div class="form-group">
<label for="email">Email :</label>
<input type="email" id="email" name="email" required>
</div>
<!-- Bouton -->
<div class="form-group">
<button type="submit">Envoyer</button>
</div>
</form>
name="prenom"
name="date_naissance"
name="code_postal"
name="competences[]" <!-- Pour tableaux -->
name="p" <!-- Trop court -->
name="firstName" <!-- camelCase peu standard en PHP -->
name="competences" <!-- Sans [] pour checkbox multiples -->
<!-- MAUVAIS -->
<input type="text" name="nom" placeholder="Votre nom">
<!-- BON -->
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom"
placeholder="Ex: Dupont">
Pourquoi ? Le placeholder disparaît à la saisie et n'est pas lu par les lecteurs d'écran
<!-- Pays par défaut -->
<select name="pays">
<option value="fr" selected>France</option>
<option value="be">Belgique</option>
</select>
<!-- Date du jour -->
<input type="date" name="date"
value="<?= date('Y-m-d') ?>">
<!-- Case cochée par défaut -->
<input type="checkbox" name="newsletter" checked>
<!-- Radio présélectionné -->
<input type="radio" name="civilite" value="mr" checked>
<input type="text" name="nom"
autocomplete="family-name">
<input type="text" name="prenom"
autocomplete="given-name">
<input type="email" name="email"
autocomplete="email">
<input type="tel" name="tel"
autocomplete="tel">
<input type="text" name="adresse"
autocomplete="street-address">
Token CSRF pour empêcher les attaques Cross-Site Request Forgery
<form action="traitement.php" method="POST">
<!-- Token de sécurité -->
<input type="hidden"
name="csrf_token"
value="<?= $_SESSION['csrf_token'] ?>">
<!-- Reste du formulaire -->
<input type="email" name="email">
<button type="submit">Envoyer</button>
</form>
<!-- IMPORTANT : enctype pour les fichiers -->
<form action="upload.php"
method="POST"
enctype="multipart/form-data">
<label for="cv">CV (PDF, max 2 Mo) :</label>
<input type="file"
id="cv"
name="cv"
accept=".pdf"
required>
<!-- Multiples fichiers -->
<label for="photos">Photos :</label>
<input type="file"
id="photos"
name="photos[]"
accept="image/*"
multiple>
<button type="submit">Envoyer</button>
</form>
<form action="contact.php" method="POST" class="contact-form">
<fieldset>
<legend>Vos informations</legend>
<div class="form-group">
<label for="nom">Nom * :</label>
<input type="text" id="nom" name="nom"
required autocomplete="family-name">
</div>
<div class="form-group">
<label for="email">Email * :</label>
<input type="email" id="email" name="email"
required autocomplete="email">
</div>
<div class="form-group">
<label for="tel">Téléphone :</label>
<input type="tel" id="tel" name="tel"
pattern="0[1-9][0-9]{8}"
placeholder="0612345678">
</div>
</fieldset>
<fieldset>
<legend>Votre message</legend>
<div class="form-group">
<label for="sujet">Sujet * :</label>
<select id="sujet" name="sujet" required>
<option value="">-- Choisir --</option>
<option value="info">Demande d'information</option>
<option value="support">Support technique</option>
<option value="autre">Autre</option>
</select>
</div>
<div class="form-group">
<label for="message">Message * :</label>
<textarea id="message" name="message"
rows="6" required
minlength="10" maxlength="500"></textarea>
</div>
</fieldset>
<div class="form-group">
<label>
<input type="checkbox" name="rgpd" required>
J'accepte la politique de confidentialité *
</label>
</div>
<input type="hidden" name="csrf_token"
value="<?= $_SESSION['csrf_token'] ?>">
<div class="form-group">
<button type="submit">✉️ Envoyer le message</button>
<button type="reset">🔄 Réinitialiser</button>
</div>
</form>
| text, email, password | Texte de base |
| number, date, time, tel, url | Types spécialisés |
| checkbox, radio | Choix multiples / unique |
| file, color, range | Éléments spéciaux |
À vous de jouer : créez votre premier formulaire complet !