Formulaire en PHP
Recevoir, valider et sécuriser les données d’un formulaire : le côté serveur, pas à pas.
- GET et POST
- Validation
- Upload
Bases HTML des Formulaires
Comprenez la structure HTML fondamentale des formulaires avant d'ajouter la logique PHP.
1 Structure HTML de Base
Éléments essentiels :
php
<!-- Formulaire de base -->
<form method="POST" action="traitement.php">
<!-- Champ texte -->
<input type="text" name="nom" required>
<!-- Champ email -->
<input type="email" name="email" required>
<!-- Bouton d'envoi -->
<button type="submit">Envoyer</button>
</form>
Attributs importants :
- method : GET ou POST
- action : fichier PHP de traitement
- name : identifiant pour PHP
- required : champ obligatoire
Types de champs HTML5 :
php
type="text"
Texte simple (nom, prénom)
php
type="email"
Adresse email avec validation automatique
php
type="password"
Mot de passe masqué
php
type="number"
Nombres avec min/max
php
type="date"
Sélecteur de date
php
type="tel"
Numéro de téléphone
php
type="file"
Upload de fichiers
2 Éléments de Formulaire Avancés
Select et Options :
php
<!-- Liste déroulante -->
<select name="pays" required>
<option value="">Choisir un pays</option>
<option value="fr">France</option>
<option value="be">Belgique</option>
<option value="ch">Suisse</option>
</select>
<!-- Zone de texte -->
<textarea name="message" rows="4"
placeholder="Votre message...">
</textarea>
Checkboxes et Radio :
php
<!-- Cases à cocher -->
<input type="checkbox" name="hobbies[]"
value="sport" id="sport">
<label for="sport">Sport</label>
<input type="checkbox" name="hobbies[]"
value="lecture" id="lecture">
<label for="lecture">Lecture</label>
<!-- Boutons radio -->
<input type="radio" name="sexe"
value="M" id="homme">
<label for="homme">Homme</label>
<input type="radio" name="sexe"
value="F" id="femme">
<label for="femme">Femme</label>
GET vs POST : Récupération des Données
Découvrez la différence entre GET et POST et comment récupérer les données envoyées par un formulaire en PHP.
1 Méthode GET
HTML - Formulaire GET :
php
<!-- search.html -->
<form method="GET" action="recherche.php">
<label for="q">Rechercher :</label>
<input type="text" name="q" id="q"
placeholder="Votre recherche...">
<select name="categorie">
<option value="tous">Toutes catégories</option>
<option value="produits">Produits</option>
<option value="articles">Articles</option>
</select>
<button type="submit">Rechercher</button>
</form>
Caractéristiques GET :
- Données visibles dans l'URL
- Parfait pour recherches, filtres
- URLs partageables
- Limité en taille (~2000 caractères)
- Peut être mis en cache
PHP - Traitement GET :
php
// recherche.php
<?php
// Récupération des données GET
$recherche = $_GET['q'] ?? '';
$categorie = $_GET['categorie'] ?? 'tous';
// Nettoyage des données
$recherche = trim($recherche);
$recherche = htmlspecialchars($recherche);
// Affichage des résultats
if (!empty($recherche)) {
echo "<h2>Recherche : $recherche</h2>";
echo "<p>Catégorie : $categorie</p>";
// Logique de recherche ici...
$resultats = rechercher($recherche, $categorie);
foreach ($resultats as $resultat) {
echo "<div>$resultat</div>";
}
} else {
echo "<p>Veuillez saisir une recherche.</p>";
}
?>
URL résultante :
php
recherche.php?q=macbook&categorie=produits
2 Méthode POST
HTML - Formulaire POST :
php
<!-- contact.html -->
<form method="POST" action="contact.php">
<label for="nom">Nom complet :</label>
<input type="text" name="nom" id="nom" required>
<label for="email">Email :</label>
<input type="email" name="email" id="email" required>
<label for="message">Message :</label>
<textarea name="message" id="message"
rows="5" required></textarea>
<input type="checkbox" name="newsletter"
value="1" id="newsletter">
<label for="newsletter">Newsletter</label>
<button type="submit">Envoyer</button>
</form>
PHP - Traitement POST :
php
// contact.php
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Récupération des données POST
$nom = trim($_POST['nom'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');
$newsletter = isset($_POST['newsletter']);
// Validation de base
if (empty($nom) || empty($email) || empty($message)) {
echo "Tous les champs sont obligatoires !";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo "Email invalide !";
} else {
// Traitement réussi
echo "<h2>Message reçu !</h2>";
echo "<p>Merci $nom, nous vous répondrons à $email</p>";
if ($newsletter) {
echo "<p>✓ Inscription newsletter</p>";
}
}
}
?>
Caractéristiques POST :
- Données cachées (pas dans l'URL)
- Parfait pour formulaires sensibles
- Taille illimitée (dans les limites du serveur)
- Peut envoyer des fichiers
- Pas de cache navigateur
Validation et Sécurisation
Apprenez à valider et sécuriser les données de vos formulaires pour éviter les failles de sécurité.
1 Validation des Données
Fonctions de validation PHP :
php
<?php
// Validation email
function validerEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
// Validation nom (lettres + espaces)
function validerNom($nom) {
return preg_match('/^[a-zA-ZÀ-ÿ\s]{2,50}$/', $nom);
}
// Validation âge
function validerAge($age) {
$age = (int)$age;
return $age >= 0 && $age <= 120;
}
// Validation téléphone français
function validerTelephone($tel) {
$pattern = '/^(?:(?:\+|00)33|0)\s*[1-9](?:[\s.-]*\d{2}){4}$/';
return preg_match($pattern, $tel);
}
?>
Validation complète d'un formulaire :
php
<?php
$erreurs = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Récupération et nettoyage
$nom = trim($_POST['nom'] ?? '');
$email = trim($_POST['email'] ?? '');
$age = $_POST['age'] ?? '';
// Validations
if (empty($nom)) {
$erreurs[] = "Le nom est obligatoire";
} elseif (!validerNom($nom)) {
$erreurs[] = "Nom invalide (2-50 caractères)";
}
if (empty($email)) {
$erreurs[] = "L'email est obligatoire";
} elseif (!validerEmail($email)) {
$erreurs[] = "Email invalide";
}
if (!empty($age) && !validerAge($age)) {
$erreurs[] = "Âge invalide (0-120)";
}
// Traitement si aucune erreur
if (empty($erreurs)) {
// Traitement des données valides...
echo "Formulaire validé !";
}
}
?>
2 Sécurisation des Données
Protection XSS :
php
<?php
// Échappement pour affichage HTML
function echapper($texte) {
return htmlspecialchars($texte, ENT_QUOTES, 'UTF-8');
}
// Nettoyage avancé
function nettoyer($texte) {
$texte = trim($texte);
$texte = stripslashes($texte);
$texte = strip_tags($texte);
return $texte;
}
// Exemple d'utilisation
$nom_utilisateur = nettoyer($_POST['nom']);
echo "Bonjour " . echapper($nom_utilisateur);
?>
Protection contre XSS :
- htmlspecialchars() pour l'affichage
- strip_tags() pour supprimer HTML
- filter_var() pour validation
- Toujours échapper avant affichage
Protection CSRF :
php
<?php
session_start();
// Génération token CSRF
function genererTokenCSRF() {
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
// Vérification token CSRF
function verifierTokenCSRF($token) {
return isset($_SESSION['csrf_token']) &&
hash_equals($_SESSION['csrf_token'], $token);
}
// Traitement formulaire
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$token = $_POST['csrf_token'] ?? '';
if (!verifierTokenCSRF($token)) {
die('Token CSRF invalide !');
}
// Traitement sécurisé...
}
?>
<!-- Dans le formulaire HTML -->
<input type="hidden" name="csrf_token"
value="<?= genererTokenCSRF() ?>">
Upload de Fichiers
Apprenez à gérer l'upload de fichiers de manière sécurisée avec PHP.
1 Upload de Fichier Simple
HTML - Formulaire d'upload :
php
<!-- IMPORTANT: enctype="multipart/form-data" -->
<form method="POST" action="upload.php"
enctype="multipart/form-data">
<label for="fichier">Choisir un fichier :</label>
<input type="file" name="fichier" id="fichier"
accept=".jpg,.jpeg,.png,.gif" required>
<label for="description">Description :</label>
<input type="text" name="description"
id="description" required>
<button type="submit">Uploader</button>
</form>
Points importants :
- enctype="multipart/form-data" obligatoire
- method="POST" requis pour les fichiers
- accept limite les types de fichiers
- Configuration php.ini à vérifier
PHP - Traitement de l'upload :
php
// upload.php
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Vérifier si fichier uploadé
if (isset($_FILES['fichier']) && $_FILES['fichier']['error'] === 0) {
// Informations du fichier
$fichier = $_FILES['fichier'];
$nom_fichier = $fichier['name'];
$taille_fichier = $fichier['size'];
$type_fichier = $fichier['type'];
$fichier_temp = $fichier['tmp_name'];
// Validation de base
$extensions_autorisees = ['jpg', 'jpeg', 'png', 'gif'];
$extension = strtolower(pathinfo($nom_fichier, PATHINFO_EXTENSION));
if (in_array($extension, $extensions_autorisees)) {
// Dossier de destination
$dossier_upload = 'uploads/';
$nouveau_nom = uniqid() . '.' . $extension;
$chemin_destination = $dossier_upload . $nouveau_nom;
// Déplacer le fichier
if (move_uploaded_file($fichier_temp, $chemin_destination)) {
echo "Fichier uploadé avec succès !";
} else {
echo "Erreur lors de l'upload.";
}
} else {
echo "Extension non autorisée.";
}
}
}
?>
Projet Complet : Formulaire de Contact Avancé
Créons un formulaire de contact complet avec validation, sécurisation et persistance des données.
contact_complet.php - Formulaire Avancé
php
<?php
/**
* Formulaire de Contact Avancé - Projet complet PHP
* Fonctionnalités : validation, sécurisation, CSRF, upload, persistance
*/
session_start();
// CONFIGURATION
$dossier_uploads = 'uploads/';
$fichier_contacts = 'contacts.json';
$extensions_autorisees = ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx'];
$taille_max = 5 * 1024 * 1024; // 5MB
// FONCTIONS UTILITAIRES
function genererTokenCSRF() {
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
function verifierTokenCSRF($token) {
return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}
function echapper($texte) {
return htmlspecialchars($texte, ENT_QUOTES, 'UTF-8');
}
function validerEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
function validerNom($nom) {
return preg_match('/^[a-zA-ZÀ-ÿ\s\'-]{2,50}$/', $nom);
}
function validerTelephone($tel) {
$pattern = '/^(?:(?:\+|00)33|0)\s*[1-9](?:[\s.-]*\d{2}){4}$/';
return preg_match($pattern, $tel);
}
// VARIABLES
$erreurs = [];
$succes = '';
$nom = $prenom = $email = $telephone = $sujet = $message = '';
$priorite = 'normale';
$newsletter = false;
$fichier_uploade = '';
// TRAITEMENT DU FORMULAIRE
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Vérification CSRF
$token = $_POST['csrf_token'] ?? '';
if (!verifierTokenCSRF($token)) {
$erreurs[] = "Token CSRF invalide. Veuillez recharger la page.";
} else {
// RÉCUPÉRATION ET NETTOYAGE DES DONNÉES
$nom = trim($_POST['nom'] ?? '');
$prenom = trim($_POST['prenom'] ?? '');
$email = trim($_POST['email'] ?? '');
$telephone = trim($_POST['telephone'] ?? '');
$sujet = trim($_POST['sujet'] ?? '');
$message = trim($_POST['message'] ?? '');
$priorite = $_POST['priorite'] ?? 'normale';
$newsletter = isset($_POST['newsletter']);
// VALIDATIONS
if (empty($nom)) {
$erreurs[] = "Le nom est obligatoire.";
} elseif (!validerNom($nom)) {
$erreurs[] = "Le nom doit contenir 2-50 caractères (lettres, espaces, apostrophes).";
}
if (empty($prenom)) {
$erreurs[] = "Le prénom est obligatoire.";
} elseif (!validerNom($prenom)) {
$erreurs[] = "Le prénom doit contenir 2-50 caractères (lettres, espaces, apostrophes).";
}
if (empty($email)) {
$erreurs[] = "L'email est obligatoire.";
} elseif (!validerEmail($email)) {
$erreurs[] = "L'adresse email n'est pas valide.";
}
if (!empty($telephone) && !validerTelephone($telephone)) {
$erreurs[] = "Le numéro de téléphone n'est pas valide.";
}
if (empty($sujet)) {
$erreurs[] = "Le sujet est obligatoire.";
} elseif (strlen($sujet) < 5 || strlen($sujet) > 100) {
$erreurs[] = "Le sujet doit contenir entre 5 et 100 caractères.";
}
if (empty($message)) {
$erreurs[] = "Le message est obligatoire.";
} elseif (strlen($message) < 20 || strlen($message) > 1000) {
$erreurs[] = "Le message doit contenir entre 20 et 1000 caractères.";
}
if (!in_array($priorite, ['faible', 'normale', 'haute'])) {
$priorite = 'normale';
}
// TRAITEMENT DE L'UPLOAD (OPTIONNEL)
if (isset($_FILES['piece_jointe']) && $_FILES['piece_jointe']['error'] === UPLOAD_ERR_OK) {
$fichier = $_FILES['piece_jointe'];
$nom_fichier = $fichier['name'];
$taille_fichier = $fichier['size'];
$fichier_temp = $fichier['tmp_name'];
// Validation du fichier
$extension = strtolower(pathinfo($nom_fichier, PATHINFO_EXTENSION));
if (!in_array($extension, $extensions_autorisees)) {
$erreurs[] = "Extension de fichier non autorisée. Extensions permises : " . implode(', ', $extensions_autorisees);
} elseif ($taille_fichier > $taille_max) {
$erreurs[] = "Le fichier est trop volumineux. Taille maximum : 5 MB.";
} else {
// Créer le dossier si nécessaire
if (!is_dir($dossier_uploads)) {
mkdir($dossier_uploads, 0755, true);
}
// Nom sécurisé
$nouveau_nom = uniqid('contact_') . '.' . $extension;
$chemin_destination = $dossier_uploads . $nouveau_nom;
if (move_uploaded_file($fichier_temp, $chemin_destination)) {
$fichier_uploade = $nouveau_nom;
} else {
$erreurs[] = "Erreur lors de l'upload du fichier.";
}
}
}
// SAUVEGARDE SI AUCUNE ERREUR
if (empty($erreurs)) {
$contact = [
'id' => uniqid(),
'date' => date('Y-m-d H:i:s'),
'nom' => $nom,
'prenom' => $prenom,
'email' => $email,
'telephone' => $telephone,
'sujet' => $sujet,
'message' => $message,
'priorite' => $priorite,
'newsletter' => $newsletter,
'fichier' => $fichier_uploade,
'ip' => $_SERVER['REMOTE_ADDR'] ?? 'inconnue'
];
// Lire les contacts existants
$contacts = [];
if (file_exists($fichier_contacts)) {
$json = file_get_contents($fichier_contacts);
$contacts = json_decode($json, true) ?: [];
}
// Ajouter le nouveau contact
$contacts[] = $contact;
// Sauvegarder
if (file_put_contents($fichier_contacts, json_encode($contacts, JSON_PRETTY_PRINT))) {
$succes = "Votre message a été envoyé avec succès ! Nous vous répondrons dans les plus brefs délais.";
// Réinitialiser le formulaire
$nom = $prenom = $email = $telephone = $sujet = $message = '';
$priorite = 'normale';
$newsletter = false;
// Régénérer le token CSRF
unset($_SESSION['csrf_token']);
} else {
$erreurs[] = "Erreur lors de la sauvegarde. Veuillez réessayer.";
}
}
}
}
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Formulaire de Contact Avancé - PHP</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #8b5cf6, #3b82f6);
color: white;
padding: 40px;
text-align: center;
}
.header h1 {
font-size: 2.5em;
margin-bottom: 10px;
}
.form-container {
padding: 40px;
}
.alert {
padding: 15px;
margin-bottom: 20px;
border-radius: 8px;
font-weight: 500;
}
.alert-success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.alert-error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.form-group {
margin-bottom: 25px;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #333;
}
.required {
color: #e74c3c;
}
input, select, textarea {
width: 100%;
padding: 12px 15px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 16px;
transition: border-color 0.3s, box-shadow 0.3s;
}
input:focus, select:focus, textarea:focus {
outline: none;
border-color: #8b5cf6;
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.1);
}
.checkbox-group {
display: flex;
align-items: center;
gap: 10px;
}
.checkbox-group input[type="checkbox"] {
width: auto;
}
.priority-group {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.priority-option {
display: flex;
align-items: center;
gap: 8px;
padding: 10px;
border: 2px solid #e1e5e9;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
}
.priority-option:hover {
border-color: #8b5cf6;
background: #f8f7ff;
}
.priority-option input[type="radio"] {
width: auto;
}
.priority-option.faible { border-color: #10b981; }
.priority-option.normale { border-color: #3b82f6; }
.priority-option.haute { border-color: #ef4444; }
.file-input {
position: relative;
overflow: hidden;
display: inline-block;
cursor: pointer;
background: #f8f9fa;
border: 2px dashed #dee2e6;
border-radius: 8px;
padding: 30px;
text-align: center;
width: 100%;
transition: all 0.3s;
}
.file-input:hover {
border-color: #8b5cf6;
background: #f8f7ff;
}
.file-input input[type="file"] {
position: absolute;
left: -9999px;
}
.submit-btn {
background: linear-gradient(135deg, #8b5cf6, #3b82f6);
color: white;
padding: 15px 40px;
border: none;
border-radius: 10px;
font-size: 18px;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.3s;
width: 100%;
}
.submit-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(139, 92, 246, 0.3);
}
.stats {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
margin-top: 30px;
text-align: center;
color: #666;
font-size: 14px;
}
@media (max-width: 768px) {
.form-row {
grid-template-columns: 1fr;
}
.priority-group {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>📧 Contact Avancé</h1>
<p>Formulaire complet avec validation, sécurisation et upload</p>
</div>
<div class="form-container">
<?php if ($succes): ?>
<div class="alert alert-success">
✅ <?= echapper($succes) ?>
</div>
<?php endif; ?>
<?php if (!empty($erreurs)): ?>
<div class="alert alert-error">
❌ <strong>Erreurs détectées :</strong>
<ul style="margin-top: 10px; padding-left: 20px;">
<?php foreach ($erreurs as $erreur): ?>
<li><?= echapper($erreur) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="POST" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" value="<?= genererTokenCSRF() ?>">
<div class="form-row">
<div class="form-group">
<label for="nom">Nom <span class="required">*</span></label>
<input type="text" id="nom" name="nom" value="<?= echapper($nom) ?>"
placeholder="Votre nom de famille" required>
</div>
<div class="form-group">
<label for="prenom">Prénom <span class="required">*</span></label>
<input type="text" id="prenom" name="prenom" value="<?= echapper($prenom) ?>"
placeholder="Votre prénom" required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="email">Email <span class="required">*</span></label>
<input type="email" id="email" name="email" value="<?= echapper($email) ?>"
placeholder="votre@email.com" required>
</div>
<div class="form-group">
<label for="telephone">Téléphone</label>
<input type="tel" id="telephone" name="telephone" value="<?= echapper($telephone) ?>"
placeholder="01 23 45 67 89">
</div>
</div>
<div class="form-group">
<label for="sujet">Sujet <span class="required">*</span></label>
<input type="text" id="sujet" name="sujet" value="<?= echapper($sujet) ?>"
placeholder="Objet de votre message" required>
</div>
<div class="form-group">
<label>Priorité</label>
<div class="priority-group">
<label class="priority-option faible">
<input type="radio" name="priorite" value="faible" <?= $priorite === 'faible' ? 'checked' : '' ?>>
🟢 Faible
</label>
<label class="priority-option normale">
<input type="radio" name="priorite" value="normale" <?= $priorite === 'normale' ? 'checked' : '' ?>>
🔵 Normale
</label>
<label class="priority-option haute">
<input type="radio" name="priorite" value="haute" <?= $priorite === 'haute' ? 'checked' : '' ?>>
🔴 Haute
</label>
</div>
</div>
<div class="form-group">
<label for="message">Message <span class="required">*</span></label>
<textarea id="message" name="message" rows="6"
placeholder="Votre message détaillé (20-1000 caractères)" required><?= echapper($message) ?></textarea>
</div>
<div class="form-group">
<label>Pièce jointe (optionnel)</label>
<div class="file-input">
<input type="file" id="piece_jointe" name="piece_jointe"
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx">
📎 Cliquez pour choisir un fichier<br>
<small>Formats acceptés : JPG, PNG, GIF, PDF, DOC, DOCX (max 5MB)</small>
</div>
</div>
<div class="form-group">
<div class="checkbox-group">
<input type="checkbox" id="newsletter" name="newsletter" value="1"
<?= $newsletter ? 'checked' : '' ?>>
<label for="newsletter">📧 Je souhaite recevoir la newsletter</label>
</div>
</div>
<button type="submit" class="submit-btn">
📤 Envoyer le message
</button>
</form>
<div class="stats">
<strong>Fonctionnalités intégrées :</strong><br>
✅ Validation côté serveur • 🛡️ Protection CSRF • 📎 Upload de fichiers •
💾 Sauvegarde JSON • 🔒 Sécurisation XSS • 📱 Design responsive
</div>
</div>
</div>
<script>
// Affichage du nom du fichier sélectionné
document.getElementById('piece_jointe').addEventListener('change', function(e) {
const fileName = e.target.files[0]?.name || 'Aucun fichier sélectionné';
const fileInput = e.target.closest('.file-input');
fileInput.innerHTML = `📎 ${fileName}<br><small>Cliquez pour changer</small>`;
fileInput.appendChild(e.target);
});
// Compteur de caractères pour le message
document.getElementById('message').addEventListener('input', function(e) {
const count = e.target.value.length;
const max = 1000;
const min = 20;
let color = '#666';
if (count < min) color = '#ef4444';
else if (count > max * 0.9) color = '#f59e0b';
else color = '#10b981';
// Afficher le compteur (si vous voulez l'ajouter)
console.log(`Caractères: ${count}/${max}`);
});
</script>
</body>
</html>
Instructions d'Installation
- 1. Créer le dossier du projet : mkdir contact_avance && cd contact_avance
- 2. Créer le fichier : Copier le code dans contact_complet.php
- 3. Créer le dossier uploads : mkdir uploads (permissions 755)
- 4. Lancer le serveur : php -S localhost:8000
- 5. Tester : Ouvrir http://localhost:8000/contact_complet.php
Fonctionnalités Intégrées
Validation Complète
Email, nom, téléphone, longueur des messages
Sécurisation
Protection CSRF, XSS, validation stricte
Upload de Fichiers
Images, PDF, documents avec validation taille/type
Persistance JSON
Sauvegarde des contacts avec métadonnées
UX Avancée
Design responsive, animations, feedback utilisateur
Maîtrisez les Formulaires PHP !
Vous savez maintenant créer des formulaires sécurisés et interactifs. Passez à l'étape suivante : les bases de données !
🎯 Ce que vous savez maintenant :
Structure HTML • Méthodes GET/POST • Validation PHP • Sécurisation XSS/CSRF • Upload de fichiers • Gestion d'erreurs • Persistance des données
Formulaires PHP maîtrisés
Récupération, validation, sécurisation et upload : votre formulaire ne fait plus confiance à ce qu’on lui envoie.