Cours RechercherCtrl K

Mini-projets Projet 2

Un livre d'or

La base de données en SQL, puis la page PHP qui reçoit les messages d'un formulaire et les affiche sans faille XSS.

1 h

À la fin de ce projet, tu sauras

  • Créer la table d'une application et la remplir
  • Lire les données dans le bon ordre
  • Traiter un formulaire en PHP et protéger l'affichage
  • Ranger ses fonctions dans un fichier séparé

Ce que tu vas construire

Un livre d'or : les visiteurs laissent un petit message, et la page affiche tous les messages, du plus récent au plus ancien. C'est le schéma de presque toutes les applications web :

  1. une base de données garde les messages (SQL) ;
  2. un formulaire HTML envoie un nouveau message ;
  3. une page PHP vérifie ce qui arrive, l'enregistre et affiche la liste.

Les cours utilisés

Attention : tout ce qu'un visiteur écrit doit passer par htmlspecialchars() avant d'être affiché. Sinon, quelqu'un peut glisser du code JavaScript dans un message, qui s'exécuterait chez tous les autres visiteurs : c'est la faille XSS.

À retenir

  • Une application web = une base de données + des formulaires + des pages qui lisent et affichent.
  • CREATE TABLE avec NOT NULL pour les champs obligatoires ; INSERT INTO … VALUES pour ajouter.
  • ORDER BY id DESC : du plus récent au plus ancien.
  • En PHP : trim($_POST["x"] ?? ""), vérifier que ce n'est pas vide, puis enregistrer.
  • Toujours htmlspecialchars() à l'affichage : contre la faille XSS.

Voir la fiche de révision de cette leçon (à imprimer ou à relire avant un contrôle)

Étape 1 · Créer la table messages

Facile

Crée la table messages avec trois colonnes : id (INTEGER PRIMARY KEY), auteur et contenu (TEXT NOT NULL). Puis ajoute deux messages :

  • id 1, auteur Léa, contenu Super site ! ;
  • id 2, auteur Tom, contenu Merci pour les cours.
index.html
Résultat

Écris une requête : elle s'exécute pendant que tu tapes, sur une base d'exemple qui repart de zéro à chaque fois.

Voir les tables de la base d'exemple

classes (3 lignes)

idnom
1BTS SIO 1
2BTS SIO 2
3Terminale STMG

eleves (7 lignes)

idprenomnomagevilleclasse_id
1LéaMartin18Chartres1
2TomBernard19Dreux2
3InèsPetit18Chartres1
4HugoDurand20Paris2
5ChloéLambert17Lucé3
6NathanDubois19Chartres1
7SarahMoreau18DreuxNULL

notes (9 lignes)

ideleve_idmatierenote
11Développement16
21Réseau12
32Développement11
42Réseau15
53Développement18
64Réseau9
76Développement13
86Réseau14
95Gestion15

Consignes à réussir

  • À faire : Les requêtes s'exécutent sans erreur
  • À faire : La table messages a les colonnes id, auteur et contenu
  • À faire : La table contient exactement les deux messages
  • À faire : auteur et contenu sont obligatoires (NOT NULL)
Toujours bloqué ? Voir une solution
CREATE TABLE messages (
  id INTEGER PRIMARY KEY,
  auteur TEXT NOT NULL,
  contenu TEXT NOT NULL
);

INSERT INTO messages (id, auteur, contenu) VALUES (1, 'Léa', 'Super site !');
INSERT INTO messages (id, auteur, contenu) VALUES (2, 'Tom', 'Merci pour les cours.');

Étape 2 · Lire les messages

Moyen

La table existe (les requêtes de l'étape 1 sont déjà en haut, avec un troisième message). Ajoute en dessous la requête que la page utilisera : elle renvoie seulement l'auteur et le contenu, du message le plus récent (le plus grand id) au plus ancien.

index.html
Résultat

Écris une requête : elle s'exécute pendant que tu tapes, sur une base d'exemple qui repart de zéro à chaque fois.

Voir les tables de la base d'exemple

classes (3 lignes)

idnom
1BTS SIO 1
2BTS SIO 2
3Terminale STMG

eleves (7 lignes)

idprenomnomagevilleclasse_id
1LéaMartin18Chartres1
2TomBernard19Dreux2
3InèsPetit18Chartres1
4HugoDurand20Paris2
5ChloéLambert17Lucé3
6NathanDubois19Chartres1
7SarahMoreau18DreuxNULL

notes (9 lignes)

ideleve_idmatierenote
11Développement16
21Réseau12
32Développement11
42Réseau15
53Développement18
64Réseau9
76Développement13
86Réseau14
95Gestion15

Consignes à réussir

  • À faire : Les requêtes s'exécutent sans erreur
  • À faire : Seulement les colonnes auteur et contenu
  • À faire : Trié du plus récent au plus ancien
  • À faire : Le résultat est le bon : Inès, Tom, puis Léa
Toujours bloqué ? Voir une solution
CREATE TABLE messages (
  id INTEGER PRIMARY KEY,
  auteur TEXT NOT NULL,
  contenu TEXT NOT NULL
);

INSERT INTO messages (id, auteur, contenu) VALUES (1, 'Léa', 'Super site !');
INSERT INTO messages (id, auteur, contenu) VALUES (2, 'Tom', 'Merci pour les cours.');
INSERT INTO messages (id, auteur, contenu) VALUES (3, 'Inès', 'Très clair, merci !');

-- ta requête :
SELECT auteur, contenu FROM messages ORDER BY id DESC;

Étape 3 · La page PHP

Pour aller plus loin

Le formulaire envoie deux champs en POST : auteur et contenu. Pour l'exercice, il envoie l'auteur Hugo et le contenu <b>Bravo</b>, qui contient du HTML : il ne doit pas être interprété.

  1. dans fonctions.php, écris afficherMessage(array $message): string qui renvoie <p><strong>auteur</strong> : contenu</p>, l'auteur et le contenu passés par htmlspecialchars() ;
  2. dans index.php, inclus fonctions.php avec require_once ;
  3. récupère $_POST["auteur"] et $_POST["contenu"] (avec ?? "" et trim) ; s'ils ne sont pas vides, ajoute le message au tableau $messages ;
  4. affiche chaque message avec foreach et ta fonction.
Résultat

Clique sur ▶ Exécuter (ou Ctrl + Entrée) pour lancer ton code.

Consignes à réussir

  • À faire : fonctions.php définit afficherMessage
  • À faire : L'affichage passe par htmlspecialchars
  • À faire : index.php inclut fonctions.php
  • À faire : Les champs vides sont refusés
  • À faire : La page affiche les trois messages ▶ vérifié quand tu exécutes
  • À faire : Le HTML du visiteur est neutralisé (&lt;b&gt;) ▶ vérifié quand tu exécutes
Toujours bloqué ? Voir une solution

index.php

<?php
// les messages déjà enregistrés (dans un vrai site, ils viendraient de la base avec un SELECT)
$messages = [
    ["auteur" => "Léa", "contenu" => "Super site !"],
    ["auteur" => "Tom", "contenu" => "Merci pour les cours."],
];

// 1. inclure fonctions.php
require_once "fonctions.php";

// 2. récupérer et vérifier le nouveau message envoyé par le formulaire
$auteur = trim($_POST["auteur"] ?? "");
$contenu = trim($_POST["contenu"] ?? "");
if ($auteur !== "" && $contenu !== "") {
    $messages[] = ["auteur" => $auteur, "contenu" => $contenu];
}

// 3. afficher tous les messages
foreach ($messages as $message) {
    echo afficherMessage($message);
}

fonctions.php

<?php

function afficherMessage(array $message): string
{
    return "<p><strong>" . htmlspecialchars($message["auteur"]) . "</strong> : " . htmlspecialchars($message["contenu"]) . "</p>";
}