Algorithmique et développement web S2 (M2202) – TD #5

Dans cette séance de TD on va créer un site web dynamique utilisant une base de données.

Lien utile : CM #3

Avant de commencer, créez dans votre répertoire m2202 un sous-répertoire m2202-td5 pour sauvegarder les exercices de cette séance (TD #5).

Dans ce répertoire m2202-td5, créez un répertoire appelé exo1 pour le premier exercice, exo2 pour le deuxième, etc.

La démocratie

Cet exercice est un problème réel : quand vous vous inscrivez à l'Université, vous payez la Contribution de Vie Étudiante et de Campus (CVEC). Une fois par an, l'Université lance un appel à projets pour investir cet argent (dans l'ordre de 13 000 €) dans les différents campus.

Tous les étudiants du site d'Arles (IUT, Faculté ALLSH, FEG, FDSP, IFSI, OSU-Institut Pythéas) peuvent proposer des projets pour améliorer la vie étudiante, qui sont ensuite évalués par une commission et éventuellement financés.

Dans ce TD nous allons construire un site web pour choisir démocratiquement les meilleurs projets proposés par l'IUT.

Exercice 1

Cet exercice contient plusieurs parties :

  • Une base de données pour sauvegarder les descriptions de projets, l'auteur, et le nombre de votes.
  • Un page d'accueil (index.php) qui affiche les projets, triés par nombre de votes, avec un lien pour voter. À la fin, il y a un formulaire pour ajouter un nouveau projet.
  • Un fichier ajouter.php pour ajouter un projet dans la base de données.
  • Un fichier voter.php pour ajouter un vote sur un projet.

Le code HTML généré par index.php peut être comme ceci :

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <title>M2202</title>
</head>
<body>
  <h1>TD #5 / Exo 1</h1>
  <ul>
    <li>
      <em>Auteur 1</em> : Description 1.<br>
      Votes : 12. <a href="voter.php?id=1">Voter</a>
    </li>
    <li>
      <em>Auteur 2</em> : Description 2.<br>
      Votes : 6. <a href="voter.php?id=2">Voter</a>
    </li>
  </ul>
  <p>
    Voulez-vous proposer un nouveau projet ?
  </p>
  <form method="post" action="ajouter.php">
    <div>
      <label for="nom">Votre nom :</label>
      <input id="nom" type="text" name="user_name">
    </div>
    <div>
      <label for="msg">Idée :</label><br>
      <textarea id="msg" name="user_message" rows="5" cols="40"></textarea>
    </div>
    <input type="submit" value="Envoyer">
  </form>
</body>
</html>

Vous pouvez créer la base de données avec phpMyAdmin ou utiliser ce script SQL :

CREATE TABLE td5exo1 (
  id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
  auteur VARCHAR(100),
  message TEXT,
  votes INT
);

Dans ce qui suit, je vous explique les étapes pour faire cet exercice.

Les fichiers

Il faut trois fichiers PHP pour cet exercice :

La base de données

Cet exercice est le premier qu'on fait avec une base de données. Il n'est pas une exception, mais la norme quand on fait un site web dynamique. Normalement, chaque page interagit avec la base de données, donc avant d'écrire une seule ligne de code PHP il faut concevoir la base de données.

Dans cet exercice, la base de donnée est déjà définie dans l’énoncé. Il y a une table appelée td5exo1 avec quatre champs :

  1. id, un identifiant numérique pour identifier chaque entrée. Sa valeur est définie automatiquement quand on ajoute une nouvelle entrée.
  2. auteur est une chaîne de caractères courte (100 caractères maximum) pour le nom de l'auteur.
  3. message est une chaîne de caractères longue pour la description du projet.
  4. votes est un nombre entier qui compte le nombre de votes de chaque projet. Il faut l'initialiser à zéro quand on ajoute une nouvelle entrée.

Sur le serveur web de MMI, vous devez ajouter cette table. Vous pouvez le faire de façon interactive avec phpMyAdmin, ou utiliser le code SQL donné dans l'énoncé.

Je vais vous expliquer la deuxième méthode :

  1. Connectez-vous sur phpMyAdmin avec les mêmes identifiants que le serveur (voir le TP #2).
  2. Cliquez sur votre base de données à gauche (elle s'appelle comme votre identifiant).
  3. Cliquez sur le bouton SQL dans la barre supérieure.
  4. Copiez le code SQL dans le champ de texte et cliquez sur Go.
Étapes pour ajouter une table sur phpMyAdmin

Le fichier index.php

La seule partie dynamique de la page index.php est la liste de projets. Il faut faire une requête à la base de données de tous les projets, en les triant par nombre de votes. La requête SQL à faire est :

SELECT * FROM td5exo1 ORDER BY votes DESC

Comme c'est un requête statique (c'est à dire, elle ne dépend pas d'une variable), on peut utiliser ce code vu en CM #3.

Pour la connexion à la base de données dans le serveur web de MMI, il faut modifier :

Le code du fichier index.php est le suivant :

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <title>M2202</title>
</head>
<body>
  <h1>Projets pour AMU à Arles</h1>
  <ul>
<?php
/* connexion à la BDD dans le serveur web de MMI
 * le nom de la base de données est votre identifiant (a19000000)
 * l'utilisateur (deuxième paramètre) est le même : a19000000
 * le mot de passe (troisième paramètre) est secret (je ne l'ai pas changé)
 */
$dbh = new PDO('mysql:host=localhost;dbname=a19000000;charset=utf8', 
               'a19000000', 
               'secret');
// requête SQL : on affiche tous les projets triés par nombre de votes descendant
$sth = $dbh->query('SELECT * FROM td5exo1 ORDER BY votes DESC');
// afficher les données
while ($row = $sth->fetch()) {
  echo '<li>';
  echo '<em>' . $row['auteur'] . '</em> : ';
  echo $row['message'] . '<br> ';
  echo 'Votes : ' . $row['votes'] . ' ';
  echo '<a href="voter.php?id=' . $row['id'] . '">Voter</a>';
  echo '</li>';
}
// terminer le traitement de la requête
$sth->closeCursor();
?>
  </ul>
  <p>
    Voulez-vous proposer un nouveau projet ?
  </p>
  <form method="post" action="ajouter.php">
    <div>
      <label for="nom">Votre nom :</label>
      <input id="nom" type="text" name="user_name">
    </div>
    <div>
      <label for="msg">Idée :</label><br>
      <textarea id="msg" name="user_message" rows="5" cols="40"></textarea>
    </div>
    <input type="submit" value="Envoyer">
  </form>
</body>
</html>

Le fichier ajouter.php

Dans ce fichier on utilise les données entrées dans le formulaire (qu'on retrouve dans la variable superglobale $_POST) pour insérer une nouvelle entrée dans la base de données.

Nous avons vu en cours comment ajouter une entrée ici. Ce fichier est alors facile :

<?php
// connexion à la BDD
$dbh = new PDO('mysql:host=localhost;dbname=a19000000;charset=utf8', 
               'a19000000', 
               'secret');
// requête SQL preparée pour ajouter une nouvelle entrée
$sth = $dbh->prepare('INSERT INTO td5exo1(auteur, message, votes) 
                      VALUES(:auteur, :message, :votes)');
$data = array(
  'auteur'  => $_POST['user_name'],
  'message' => $_POST['user_message'],
  'votes'   => 0
);
$sth->execute($data);
$sth->closeCursor();

header('Location: index.php');
?>

Le fichier voter.php

Dans ce fichier on incrémente le nombre de votes d'un projet. On sait lequel parce qu'on passe une variable par la méthode GET.

Pour incrémenter le nombre de votes, il faut modifier la base de données, et cela se fait en deux étapes :

  1. D'abord, on récupère le nombre de votes du projet avec une requête SQL. C'est une requête préparée, car elle contient une variable pour choisir le projet.
  2. Ensuite, on modifie cette entrée dans la base de données. La nouvelle valeur pour le champs votes est celle qu'on a récupéré, plus 1. Cette requête est préparée aussi.

La seule difficulté de ce fichier est faire les deux requêtes préparées, mais nous avons cet exemple du CM #3.

Le code du fichier voter.php est le suivant :

<?php
// connexion à la BDD
$dbh = new PDO('mysql:host=localhost;dbname=a19000000;charset=utf8', 
               'a19000000', 
               'secret');

// trouver le nombre de votes
$sth = $dbh->prepare('SELECT votes FROM td5exo1 WHERE id = :id');
$valeurs = array('id' => $_GET['id']);
$sth->execute($valeurs);
$row = $sth->fetch();
$votes_avant = $row['votes']; 

// le modifier
$sth = $dbh->prepare('UPDATE td5exo1 
                      SET votes = :votes
                      WHERE id = :id');
$valeurs = array('votes' => $votes_avant + 1,
                 'id' => $_GET['id']);
$sth->execute($valeurs);
$sth->closeCursor();

// on renvoie l'utilisateur vers la page d'accueil
header('Location: index.php');
?>

Conclusion

Cet exercice peut être encore amélioré avec une validation du formulaire : vérifier que le nom de l'auteur n'est pas vide, limiter la longueur de la description, etc. Je ne l'ai pas demandé dans cet exercice pour faire plus simple, mais il faudrait le faire pour un vrai site web dynamique.

J'ai fait cet exercice pour l'utiliser pour de vrai. Je l'ai mis sur cette page web pour que vous puissiez choisir des projets pour cette année. Je pense que Mme Vallicari vous présentera la CVEC bientôt.

Pourtant, dans ce contexte de crise, on aurait pu faire quelque chose encore plus intéressant : un site web dans lequel les utilisateurs disent à quelle heure et dans quel supermarché ils vont aller. On pourrait afficher le nombre de personnes dans chaque créneau et supermarché pour éviter les agglomérations. Vous avez maintenant les compétences pour faire cela, vous pouvez aider les gens.