Aller au contenu principal

Module 4 – PHP & Formulaires

Niveau 1 – PHP fondamentaux


Objectifs

GET vs POST, récupération des données ($_GET, $_POST), validation côté serveur et protection XSS avec htmlspecialchars. On termine par un formulaire d’inscription sécurisé de A à Z.


Théorie

GET vs POST

CritèreGETPOST
DonnéesDans l’URL (query string)Dans le corps de la requête HTTP
VisibilitéVisibles dans la barre d’adresse, l’historique, les logsNon visibles dans l’URL
TailleLimitée (longueur d’URL)Corps de requête plus adapté aux gros volumes
Usage typiqueRecherche, filtres, liens partageablesEnvoi de formulaires (inscription, connexion, envoi de fichier)
Ré-envoiFavoris / actualisation = même requêteLe navigateur peut demander de confirmer le ré-envoi

Règle pratique :

  • GET : lecture, recherche, navigation (pas de modification sensible).
  • POST : création ou modification de données (inscription, connexion, formulaire de contact).

En PHP, les données GET sont dans $_GET, les données POST dans $_POST. Ce sont des tableaux associatifs (clé = nom du champ).


Récupérer les données en PHP

Exemple – Formulaire en GET :

<form method="get" action="search.php">
<input type="text" name="q" placeholder="Search">
<button type="submit">Search</button>
</form>

URL après envoi : search.php?q=laravel

// search.php
$query = $_GET["q"] ?? ""; // ?? = default value if key is missing
echo "Search: " . htmlspecialchars($query);

Exemple – Formulaire en POST :

<form method="post" action="register.php">
<input type="text" name="first_name" required>
<input type="email" name="email" required>
<button type="submit">Sign up</button>
</form>
// register.php
$firstName = $_POST["first_name"] ?? "";
$email = $_POST["email"] ?? "";
// Always check request method is POST before processing
if ($_SERVER["REQUEST_METHOD"] === "POST") {
// process registration
}

Important : Utiliser ?? pour éviter les notices si une clé est absente (utilisateur qui accède directement à la page sans envoyer le formulaire).


Validation simple

La validation = vérifier que les données sont présentes, au bon format et acceptables avant de les utiliser ou les enregistrer.

Exemple de validation basique :

$errors = [];

if (empty(trim($_POST["first_name"] ?? ""))) {
$errors[] = "First name is required.";
}
if (empty(trim($_POST["email"] ?? ""))) {
$errors[] = "Email is required.";
} elseif (!filter_var($_POST["email"], FILTER_VALIDATE_EMAIL)) {
$errors[] = "Email is invalid.";
}

if (count($errors) === 0) {
// Process registration
} else {
// Re-display form with error messages
}

Fonctions utiles :

  • empty() : vide (chaîne vide, 0, null, false, tableau vide)
  • trim($s) : enlever espaces début/fin
  • filter_var($email, FILTER_VALIDATE_EMAIL) : valider un email
  • Longueur min/max, regex, etc. pour des règles plus avancées

Sécurité basique : XSS et htmlspecialchars

XSS (Cross-Site Scripting) : un attaquant injecte du JavaScript (ou du HTML) dans une page. Si ce contenu est affiché sans échappement, le script s’exécute dans le navigateur des autres utilisateurs (vol de session, redirection, etc.).

Défense indispensable : Toujours échapper tout contenu qui vient de l’utilisateur (ou de la BDD) avant de l’afficher dans du HTML.

En PHP : `htmlspecialchars()``.

$firstName = $_POST["first_name"] ?? "";
echo "Hello, " . htmlspecialchars($firstName);

Pourquoi ça suffit (pour l’affichage) :
Les caractères <, >, ", ', & sont convertis en entités HTML (&lt;, &gt;, etc.), donc le navigateur ne les interprète plus comme du code.

Bon usage :

htmlspecialchars($text, ENT_QUOTES, "UTF-8");
  • ENT_QUOTES : échapper aussi les guillemets simples.
  • "UTF-8" : encodage de la chaîne (important pour les accents).

Règle d’or : Tout ce qui vient de l’utilisateur ou de la base et qui est affiché dans du HTML doit passer par htmlspecialchars() (ou un équivalent dans un framework).


Exemple complet : formulaire avec validation et échappement

Fichier unique : formulaire + traitement (pattern courant en PHP simple).

<?php
$errors = [];
$success = false;
$firstName = "";
$email = "";

if ($_SERVER["REQUEST_METHOD"] === "POST") {
$firstName = trim($_POST["first_name"] ?? "");
$email = trim($_POST["email"] ?? "");

if ($firstName === "") {
$errors[] = "First name is required.";
}
if ($email === "") {
$errors[] = "Email is required.";
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Email is invalid.";
}

if (count($errors) === 0) {
// Save to DB, send email, etc.
$success = true;
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sign up</title>
</head>
<body>
<?php if ($success): ?>
<p>Sign up successful. Welcome, <?= htmlspecialchars($firstName, ENT_QUOTES, "UTF-8") ?>!</p>
<?php else: ?>
<?php foreach ($errors as $err): ?>
<p class="error"><?= htmlspecialchars($err, ENT_QUOTES, "UTF-8") ?></p>
<?php endforeach; ?>

<form method="post" action="">
<label>First name <input type="text" name="first_name" value="<?= htmlspecialchars($firstName, ENT_QUOTES, "UTF-8") ?>" required></label>
<label>Email <input type="email" name="email" value="<?= htmlspecialchars($email, ENT_QUOTES, "UTF-8") ?>" required></label>
<button type="submit">Sign up</button>
</form>
<?php endif; ?>
</body>
</html>

Points importants :

  • value="<?= htmlspecialchars($firstName, ...) ?>" : réafficher la valeur saisie en la protégeant contre le XSS.
  • <?= ... ?> est un raccourci pour <?php echo ... ?>.
  • Les messages d’erreur sont aussi échappés avant affichage.

Bonnes pratiques

  1. Vérifier la méthode : if ($_SERVER["REQUEST_METHOD"] === "POST") avant de traiter un formulaire.
  2. Toujours utiliser ?? pour lire $_GET / $_POST (éviter les notices).
  3. Valider côté serveur : ne jamais faire confiance aux données du client (HTML5 required / pattern = confort utilisateur, pas une sécurité).
  4. Échapper à l’affichage : htmlspecialchars(..., ENT_QUOTES, "UTF-8") pour tout contenu dynamique dans le HTML.
  5. Réafficher les champs en cas d’erreur pour ne pas faire ressaisir tout le formulaire.

Exercices

Exercice 1 – Créer un formulaire de recherche (GET) avec un champ q. La page affiche « Vous avez cherché : [valeur] » en échappant la valeur.

Exercice 2 – Même chose en POST. Expliquer pourquoi en production on préfère POST pour un formulaire de connexion.

Exercice 3 – Ajouter la validation : prénom entre 2 et 50 caractères, email valide. Afficher les erreurs au-dessus du formulaire.

Details

Indication Exercice 3 Utiliser mb_strlen($firstName) pour la longueur (UTF-8) et filter_var($email, FILTER_VALIDATE_EMAIL). Stocker les erreurs dans un tableau et les afficher dans une boucle avec htmlspecialchars.


Projet : Formulaire d'inscription sécurisé

Cahier des charges minimal :

  1. Champs : prénom, nom, email, mot de passe, confirmation mot de passe.
  2. Méthode : POST, action vers la même page (traitement dans le même script).
  3. Validation côté serveur :
    • Champs obligatoires (prénom, nom, email, mot de passe, confirmation).
    • Email valide (filter_var).
    • Mot de passe et confirmation identiques.
    • Longueur mot de passe ≥ 8 caractères (à adapter selon votre politique).
  4. Sécurité affichage :
    • Toutes les sorties utilisateur dans le HTML passent par htmlspecialchars(..., ENT_QUOTES, "UTF-8").
    • Les value des champs sont pré-remplies en cas d’erreur (sauf mot de passe : ne jamais réafficher).
  5. UX : en cas d’erreur, réafficher le formulaire avec les messages d’erreur listés en haut.

Pour aller plus loin (hors module 4 mais à garder en tête) :

  • En production : hasher le mot de passe avec password_hash() avant stockage (voir module 8 / Laravel).
  • CSRF : en Laravel ou avec des tokens, on protégera les formulaires contre la falsification (niveau 3/4).

Critères de réussite :

  • Aucune donnée utilisateur affichée sans htmlspecialchars.
  • Validation cohérente et messages d’erreur clairs.
  • Formulaire réutilisable après une erreur (sauf mot de passe).

Quiz – Module 4

Q1. Quand utiliser GET et quand utiliser POST pour un formulaire ?
Q2. Où se trouvent les données d’un formulaire POST en PHP ?
Q3. À quoi sert htmlspecialchars() et pourquoi est-ce important ?
Q4. Pourquoi ne doit-on jamais se fier uniquement à la validation HTML (required, pattern) ?
Q5. Que faire des champs en cas d’erreur de validation (sauf mot de passe) ?

Réponses

R1. GET pour la lecture / recherche (données dans l’URL). POST pour l’envoi de données sensibles ou qui modifient l’état (inscription, connexion, etc.).

R2. Dans la superglobale $_POST (tableau associatif : nom du champ → valeur).

R3. À échapper le contenu pour l’affichage HTML (convertir <, >, ", etc. en entités). C’est la protection de base contre le XSS (injection de script dans la page).

R4. Parce que l’utilisateur peut contourner le HTML (requête directe, outil dev). La vraie validation doit être côté serveur en PHP.

R5. Réafficher les valeurs dans les champs (value="...") pour éviter que l’utilisateur doive tout ressaisir. Ne jamais réafficher le mot de passe (sécurité et bonnes pratiques).


Suite

Niveau 1 terminé. Enchaîner avec l’Examen Niveau 1 (fichier dédié), puis le Niveau 2 – PHP avancé (Module 5 : POO).