Comment faire un livre d'or en PHP

Dans ce cours, nous allons donc voir comment réaliser un livre d'or ; script étant d'ailleurs le plus simple à réaliser en PHP.

Pour ceux qui ne le savent pas encore, un livre d'or est un livre que tous les visiteurs d'un site peuvent signer, en y laissant un petit message de sympathie concernant ce même site.

Réfléchissons alors de quoi avons besoin pour réaliser un tel script.
Il nous faudra d'une part, une table de bases de données de type MySQL permettant de sauvegarder toutes les signatures de notre livre d'or.
Puis en ce qui concerne le livre d'or en lui même, nous aurons besoin d'une page permettant d'afficher toutes les signatures du livre d'or, ainsi qu'une page permettant de signer le livre d'or.

En conclusion, on aura alors besoin de :
  • une table MySQL
  • une page PHP affichant les signatures
  • une page PHP permettant de signer ce livre


Entre parenthèses, vous noterez que les deux pages que nous avons à écrire, pourraient très bien être combinées pour ne former qu'une seule et même page (c'est-à-dire que l'on aurait dans ce cas la page qui affiche les signatures, et, dans cette même page, un formulaire permettant d'enregistrer une nouvelle signature), chose que nous détaillerons pas dans ce cours.

Détaillons alors nos besoins :

En ce qui concerne la table MySQL à créer, il faut savoir de quels éléments nous allons avoir besoin :
  • un attribut id de type INT avec une option AUTO_INCREMENT qui représentera la clé primaire de notre table, ce qui nous permettra de distinguer toutes les signatures de notre livre d'or.
  • un attribut auteur de type VARCHAR qui nous permettra d'enregistrer le nom de chaque signataire.
  • un attribut email de type VARCHAR permettant d'enregistrer l'adresse E-mail d'un signataire.
  • un attribut date de type datetime permettant d'enregistrer l'heure d'une signature.
  • un attribut message de type text, permettant d'enregistrer le texte même de la signature.


C'est pourquoi, avec tous ces besoins, je vous propose la table MySQL suivante :

table_livre_or.sql
CREATE TABLE livre_or (
id int(6) NOT NULL auto_increment,
auteur VARCHAR(50) NOT NULL,
email VARCHAR(50) NOT NULL,
date_signature datetime NOT NULL default '0000-00-00 00:00:00',
message text NOT NULL,
PRIMARY KEY (id)
) TYPE=MyISAM;


Tachons maintenant d'écrire notre page index.php qui affichera toutes les signatures de notre livre d'or.
Cette page sera en fait toute simple, puisque en fait, nous allons juste sélectionner dans notre base de données toutes les signatures (ordonnées par date) du livre d'or puis les afficher.

On aura alors :

index.php
<html>
<head>
<title>Index de notre livre d'or</title>
</head>
<body>

<a href="./insert_signature.php">Signer le livre d'or</a>

<br /><br />

<?php
$base = mysql_connect ('serveur', 'login', 'password');
mysql_select_db ('nom_base', $base);

$sql = 'SELECT auteur, email, date_signature, message FROM livre_or ORDER BY date_signature DESC';
$req = mysql_query($sql) or die('Erreur SQL !<br />'.$sql.'<br />'.mysql_error());

$nb_signature = mysql_num_rows($req);

if ($nb_signature == 0) {
echo 'Aucune signature.';
}
else {
while ($data = mysql_fetch_array($req)) {
sscanf($data['date_signature'], "%4s-%2s-%2s %2s:%2s:%2s", $annee, $mois, $jour, $heure, $minute, $seconde);

echo '<a href=mailto:' , htmlentities(trim($data['email'])) , '>' , htmlentities(trim($data['auteur'])) , '</a>';
echo ' le ' , $jour , '/' , $mois , '/' , $annee , ' à ' , $heure , ':' , $minute , '<br />';
echo nl2br(htmlentities(trim($data['message'])));
echo '<br /><br />';
}
}
// on libère l'espace mémoire alloué pour cette requête
mysql_free_result ($req);
// on ferme la connection à la base de données.
mysql_close ();
?>

</body>
</html>


Voyons maintenant le code de la page insert_signature.php, page qui ne pose aucun problème puisqu'il s'agit d'un formulaire où le signataire pourra mettre son nom son adresse E-mail, et déposer une signature sur le livre d'or.



Cependant, contrairement aux scripts précédents, nous allons introduire une fonctionnalité intéressante.

C'est-à-dire que lorsqu'un utilisateur remplira ce formulaire, qu'il le validera en cliquant sur le bouton de soumission, et bien, il serait agréable de faire en sorte que si le formulaire est incomplet, le formulaire réapparaisse avec les données déjà saisies par l'utilisateur (jusqu'ici, les données étaient toujours effacées).

On aura alors, par exemple :

insert_signature.php
<?php
if (isset($_POST['go']) && $_POST['go']=='Signer') {

if ((isset($_POST['auteur'])) && (isset($_POST['email'])) && (isset($_POST['message']))) {
// si les 3 variables ne sont pas vides, et si l'adresse E-mail est valide, alors, et seulement dans ce cas, on fera notre insertion dans la base
if ((!empty($_POST['auteur'])) && (!empty($_POST['email'])) && (!empty($_POST['message']))) {
// on verifie le format de l'adresse E-mail saisie
$test_mail = eregi ('^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)+$', $_POST['email']);
if ($test_mail) {
// on se connecte à notre base
$base = mysql_connect ('localhost', 'root', '');
mysql_select_db ('howto_guestbook', $base);

// on prepare notre requête d'insertion des données
$sql = 'INSERT INTO livre_or VALUES("", "'.mysql_escape_string($_POST['auteur']).'", "'.mysql_escape_string($_POST['email']).'", "'.date("Y-m-d H:i:s").'", "'.mysql_escape_string($_POST['message']).'")';

// on lance la requête
mysql_query($sql) or die('Erreur SQL !'.$sql.'<br />'.mysql_error());

// on ferme la connexion à la base de données
mysql_close();

// on redirige le visiteur vers l'accueil du livre d'or
header('location: index.php');

// on termine le script courant
exit();
}
else {
$erreur = 'Votre adresse E-mail est invalide.';
}
}
else {
$erreur = 'Au moins un des champs est vide.';
}
}
else {
$erreur = 'Les variables nécessaires au script ne sont pas définies.';
}
}
// on entre dans le cas où l'un des trois (au moins) champs n'a pas été rempli ou si l'adresse E-mail n'a pas été validée (en particulier, lorsque le visiteur charge pour la première fois cette page, vu que les 3 champs sont vides, le formulaire s'affichera). On remarque également que l'on met la valeur de chaque champs dans le value (c'est cela qui fait que si le visiteur ne remplit pas entièrement le formulaire et qu'il clique sur "Signer", et bien lorsqu'il sera redirigé vers le formulaire, ce qu'il aura déjà saisi sera conservé
?>
<html>
<head>
<title>Insertion d'une nouvelle signature</title>
</head>

<body>

<form action="insert_signature.php" method="post">
<table>
<tr><td>
[b]Auteur :[/b]
</td><td>
<input type="text" name="auteur" maxlength="30" size="50" value="<?php if (isset($_POST['auteur'])) echo htmlentities(trim($_POST['auteur'])); ?>">
</td></tr><tr><td>
[b]Adresse E-mail :[/b]
</td><td>
<input type="text" name="email" maxlength="50" size="50" value="<?php if (isset($_POST['email'])) echo htmlentities(trim($_POST['email'])); ?>">
</td></tr><tr><td>
[b]Votre message :[/b]
</td><td>
<textarea name="message" cols="50" rows="10"><?php if (isset($_POST['message'])) echo htmlentities(trim($_POST['message'])); ?></textarea>
</td></tr><tr><td><td align="right">
<input type="submit" name="go" value="Signer">
</td></tr></table>
</form>
<?php
if (isset($erreur)) echo '<br /><br />',$erreur;
?>
</body>
</html>


Et voila :)
Notre livre d'or est à présent terminé (il est du moins fonctionnel).

Et vous vous rendez bien compte que ce script est quand même le script le plus simple à réaliser en PHP (c'est pourquoi nous avons introduit un petit système permettant à l'utilisateur de ne pas tout re-remplir le formulaire si la saisie d'un champ n'a pas été validée).

Que faire en plus ?

Et bien à part l'affichage (le design) du livre d'or que je pense tout le monde modifiera, il n'y a pas vraiment de fonctionnalités à rajouter à ce livre d'or.
Un livre d'or reste un livre d'or.
Ou alors peut-être qu'une gestion de simleys ou de bb-code pourrait être sympathique.
Ainsi que, pourquoi pas, un affiche page / page, permettant de visualiser toutes les signatures sur plusieurs pages (c'est-à-dire ne pas avoir une page qui fait 3 km de long).
LoadingChargement en cours