TD6 - PHP/MySQL : Donner des avis sur des produits - Relations 1:n - Clé étrangère
Objectif
Dans ce TD6, nous allons faire un premier exemple qui utilise deux tables d’une base de données, et qui sont reliés par une relation 1:n - donc une des tables aura une clé étrangère référant à l’autre table. Comme exemple, nous allons créer un site web permettant d’afficher différents produits d’une table produit de la base de données, d’afficher le détail d’un produit, et de permettre aux utilisateurs de donner un avis sur chaque produit dans une table avis de la base de données. Le site web comprend trois pages, s’appelant sommaire-produits.php, detail-produit.php, et ajouter-avis.php.
phpMyAdmin : Création d’une table MySQL et manipulation de données
Exercice 6.1 Environnement de travail
- Démarrer dans votre environnement de travail habituel (éditeur de texte, phpMyAdmin). Aujourd’hui, nous travaillons dans le dossier td6.
Exercice 6.2 Création de deux tables de la base de données
En utilisant votre interface phpMyAdmin, créez une table dans votre base de données qui s’appelle produit avec les champs suivants : un champ INT qui s’appelle id avec les attributs clé primaire (PRIMARY comme INDEX) ainsi que “auto-increment (A_I)”, un champ TEXT qui s’appelle nom, et un champ TEXT qui s’appelle description, ainsi qu’un champ DATETIME qui s’appelle date.
Toujours avec votre interface phpMyAdmin, créez quelques enregistrement dans cette table . Pour la description du produit, pour éviter de la remplir maintenant, utilisez les trois paragraphes du texte issu de la version populaire de “Lorem ipsum” issue de la page https://fr.wikipedia.org/wiki/Faux-texte. Voici votre table résultante :
Table produit
| id | nom | description | date |
|---|---|---|---|
| INT | TEXT | TEXT | DATETIME |
| —– | ——————————– | —————— | ——————— |
| 1 | Batterie supplémentaire 20000mAh | Lorem Ipsum (…) | 2025-02-03 01:32:31 |
| 2 | Chargeur USB-C | Lorem Ipsum (…) | 2025-02-03 23:22:17 |
Toujours en utilisant votre interface phpMyAdmin, créez une table avis comme suit. N’oubliez pas, comme d’habitude, que la clé primaire id doit avoir les attributs clé primaire (PRIMARY comme INDEX) ainsi que auto-increment (A_I).
Table avis
| id | nom | texte | date | validation | id_produit |
|---|---|---|---|---|---|
| INT | TEXT | TEXT | DATETIME | INT | INT |
| —– | ——– | —————— | ——————— | ———— | ———— |
| 1 | Amaia | Fonctionne bien | 2025-02-05 03:28:03 | 1 | 1 |
| 2 | Estelle | Très bon produit | 2025-02-04 23:42:01 | 1 | 2 |
| 3 | Xabi | Joli design | 2025-02-05 23:59:17 | 1 | 1 |
Pour quel produit Estelle a laissé un avis ?
Combien d’avis ont été laissé pour la batterie supplémentaire ?
Exercice 6.3 Page web du sommaire de tous les produits
Dans cet exercice, vous allez créer une page sommaire-produits.php qui affiche un sommaire de tous les produits de la table produit de votre base de données, en affichant uniquement le nom des produits. Lorsqu’on clique sur le nom du produit, vous renvoyez vers une nouvelle page detail-produit.php en spécifiant l’identifiant du produit par l’URL, et cette page affichera le détail de du produit choisi (cet exercice ressemble beaucoup à l’exercice de créer un sommaire pour les tables de multiplications, renvoyant vers le détail des tables en passant le facteur en paramètre, sauf que nous utilisons des informations d’une base de données au lieu de les calculer…)}).
Nous allons procéder en plusieurs étapes pour arriver à ce fonctionnement :
Dans le dossier
td6, créez un document HTML dans une pagesommaire-produits.phpayant comme titre “Sommaire des produits” (la balise<title>dans l’en-tête et aussi la balise<h1>dans le corps du document).Dans un premier temps, en HTML pur et donc sans élément dynamique et sans connexion avec la base de données, affichez un sommaire de tous les noms des produits. Plus précisément, utilisez une liste (balise
<ul>) avec les noms de tous les produits.Transformez les noms des produits en lien hypertexte vers une page
detail-produit.php, en ajoutant un identifiant du produit?id=dans la cible du lien URL.Nous allons maintenant transformer ce sommaire non-dynamique pour qu’il utilise la base de données. En tout début de votre fichier (même avant la déclaration DOCTYPE), incluez la connexion à la base de données :
<?php require_once("connexion_base.php"); ?>N’oubliez pas de copier le fichier connexion_base.php du TD précédent dans votre dossier td6.
- Juste après, donc toujours au début de fichier avant toute balise HTML, ajoutez les instructions suivantes afin de récupérer tous les produits :
<?php
// exécuter une requete MySQL
$requete = "SELECT * FROM produit";
$reponse = $pdo->prepare($requete);
$reponse->execute(array());
// récupérer tous les enregistrements dans un tableau
$enregistrements = $reponse->fetchAll();
// connaitre le nombre d'enregistrements
$nombreProduits = count($enregistrements);
?>Maintenant, affichez un sommaire de tous les noms des produits de la table de votre base de données ainsi récupérés, en utilisant une liste (balise
<ul>) avec les noms de tous les produits.Transformez les noms des produits en lien hypertexte vers une page
detail-produit.php, en ajoutant l’identifiant du produit dans l’URL dans le paramètre?id=.
Utilisez bien l’identifiant id du produit, et non pas la variable d’itération (p.ex. $i$) de votre boucle, pour que la page detail-produit.php connait l’identifiant du produit.
Exercice 6.4 Page web du détail d’un produit
Comme dans l’exercice précédent, d’abord sans élément dynamique et sans connexion avec la base de données, créez un fichier
detail-produit.phpqui contient les balises HTML, avec des titres<title>et<h1>de votre choix pour le nom du produit. Complétez votre description de détail de produit par 3 paragraphes de faux texte, et en haut de votre page, mettez une image de votre choix que vous stockez dans un dossierimagesdu dossiertd6sous le nomproduit.png, et qui doit avoir une définition de 600 pixels de large et 400 pixels de haut. En bas de la page, proposez également un lien pour retourner au sommaire des produits.Modifiez votre fichier
detail-produit.php, au tout début, pour qu’il inclut le fichierconnexion_base.phpavec la fonctionrequire_once(comme d’habitude).Juste après, récupérez l’identifiant depuis l’URL
idavec la méthodeGETen tout début de page, et stockez cet identifiant dans la variable$id.Juste après, donc toujours au début de fichier avant toute balise HTML, ajoutez les instructions suivantes afin de récupérer le détail du produit ayant l’identifiant
$id:
<?php
$requete = "SELECT * FROM produit WHERE id=?";
$reponse = $pdo->prepare($requete);
$reponse->execute(array($id));
?>Notez que le point d’interrogation (?) doit être vraiment laissé tel quel - il est remplacé par l’identifiant id dans l’appel à la méthode execute qui prend comme paramètre un tableau de toutes les valeurs pour tous les points d’interrogation (?). Ce procédé de requête préparée est utilisé pour éviter des attaques malveillantes de type SQL injection (ce sera expliqué en cours, pour information : https://fr.wikipedia.org/wiki/Injection_SQL).
Notez également que le résultat de la requête sera un seul enregistrement (si un produit avec cet identifiant existe bien sûr). Il y a deux façons d’accéder à ce seul enregistrement :
- Si vous utilisez l’instruction
$enregistrements = $reponse->fetchAll();vous pouvez donc y accéder en utilisant l’index 0, donc pour récuperer le nom de produit : $enregistrements[0][...].
- Mais si vous utilisez l’instruction
$enregistrement = $reponse->fetch();pour récuperer le nom de produit, ce sera directement : $enregistrement[...].
Remplacez le texte du titre
<h1>ainsi que le contenu par le nom et la description du produit par les informations provenant de votre tableproduitde votre base de données.Créez un sous-dossier
images-produitsde votre dossierimages. Créez une image représentative pour chaque produit stocké dans votre base de données, et enregistrez toutes les images dans le sous-dossierimages-produitsavec comme nom l’identifiant du produit (doncproduit-1.pngpour le produit avec l’identifiant 1,produit-2.pngpour le produit avec l’identifiant 2, etc).Modifiez votre page pour qu’au lieu d’afficher
produit.png, vous affichez l’image correspondant au produit du dossierimages-produits, doncproduit-1.pngpour le produit avec l’identifiant 1, par exemple.
Exercice 6.5 Afficher les avis sur un produit
Dans cet exercice, dans un premier temps, our simplifier, les avis laissé ne sont pas encore spécifique à un produit. Ensuite, nous allons afficher les avis spécifiques pour le produit
Toujours dans la page
detail-produit.php, après le nom et sa description, affichez tous les avis de votre tableavis. Cela ressemble fortement à ce que vous avez fait au dernier TD pour les commentaires.Modifiez votre page
detail-produit.phppour qu’elle affiche les avis spécifiques pour le produit demandé par l’URL. Pour cela, il faut modifier la requête SQL en rajoutant une clause de type WHERE.
Exercice 6.5 Formulaire pour laisser un avis sur un produit
Toujours dans la page
detail-produit.php, en fin de page, via un formulaire, permettez de laisser un avis comme dans le précédent TD. Ce formulaire doit renvoyer vers la pageajouter-avis.phpavec la méthodepost.Afin de faire savoir sur quel produit l’avis doit être ajouté, dans votre formulaire, créez un champ
inputde typehiddenayant comme valeur l’identifiant du produit comme suit :
<input type="hidden" name="id" value="<?php echo $id; ?>" />Exercice 6.6 Insertion de l’avis dans une table d’une base de données
Dans cet exercice, vous allez créer la page ajouter-avis.php qui récupère donc les données du formulaire, et qui permet d’insérer l’avis sur un produit spécifique dans la table avis, et qui affiche un message de succès.
En tout début de votre fichier
ajouter-avis.php, incluez le fichierconnexion_base.php.Ensuite, en PHP, affectez les variables
$nom,$texteet$idavec les données saisies de votre formulaire.Ajoutez les données saisies dans la table
avisde votre base de données comme suit :
<?php
// exécuter une requete MySQL de type INSERT
$requete="INSERT INTO avis (nom, texte, date, validation, id_produit) VALUES (?,?,NOW(), 0, ?)";
$reponse=$pdo->prepare($requete);
$reponse->execute(array($nom, $texte, $id));
?>Notez que vous avez maintentant 3 points d’interrogation (?) qui seront remplacé dans l’appel à la méthode execute qui prend comme paramètre un tableau de 3 valeurs, chacune correspondant à un point d’interrogation.
Ajoutez les balises pour créer un document HTML, et dans la partie
<body>, affichez le texte “Votre avis a bien été enregistré” dans un paragraphe<p>.A la fin de votre page
ajouter-avis.php, créez un lien hypertexte avec le texte “retourner au détail du produit” qui permet de renvoyer au détail du produitdetail-produit.php!
Remarque : Ici, nous avons créé un site pour afficher des produits et de donner des avis. Bien entendu, le même fonctionnement peut être utilisé pour d’autres contenus : un produit pourrait être aussi une recette de cuisine, une nouvelle, une rumeur, une destination de vacances, un joueur de tennis, …
Exercices optionnels
Exercice 6.7 Prix des produits
Modifier l’exercice de ce TD pour que vous puissiez avoir un prix pour chaque produit. Vous pouvez afficher ce prix dans la page sommaire-produit.php et detail-produit.php. Bien sur, dans un premier temps, il faut créer un nouveau champs prix dans la table produit!
Exercice 6.8 Sommaire avec images en miniatures
Dans cet exercice, nous allons modifier la page sommaire-produit.php afin qu’il affiche une miniature de l’image à côté de chaque nom de produit. Pour cela :
Créez une miniature de chaque image avec un logiciel d’édition d’images, de par exemple 128x60 pixels, et enregistrez-la dans le même dossier
images-produits, en rajoutant-miniau nom du fichier (donc la miniature deproduit1.pngseraproduit-1-mini.png).Ajoutez l’image en miniature dans chaque élément dans la liste
ulque vous avez créée précédemment.Utilisez une table HTML de trois colonnes au lieu d’une liste, en mettant dans la colonne de gauche l’image en miniature, et dans la colonne de milieu le nom du produit, et dans la colonne de droite le prix du produit.
Notez qu’il est préférable d’utiliser cette miniature créée avec un logiciel d’édition d’images comme dans cet exercice (au lieu d’utiliser uniquement l’attibut width de la balise img) : comme le poids d’images en terme d’octets est réellement réduit, votre page web avec les miniatures utilisera moins de données du réseau et cela libère davantage de bande passante.
Comme d’habitude, les exercices sont à rendre sur moodle jusqu’à mercredi prochain, 23h59.