Module de commentaires Ajax/Php/XML et JQuery

J’ai pendant un bon moment cherché à intégrer un module de commentaires sur le site internet d’un restaurant libanais. Quasi impossible de trouver quelque chose sans base de données, sans parler des méthodes d’intégrations assez cocasses. Voici donc ce que j’ai essayé de développer dans mon coin : Légèreté (30ko), contrôle de champs, captcha rudimentaire et mise à jour de la liste des commentaires en Ajax. Je n’ai pas encore fait de module d’administration ni poussé la sécurité. Je reste bien sûr ouvert à toute contribution !

La structure des dossiers :

  • [ Dossier ] css
    • bgcaptcha.jpg
    • bgradios.jpg
    • template.css
    • validationEngine.jquery.css
  • [ Dossier ] donnees
    • index.html (pour empêcher le listing)
    • .htaccess (deny from all, pour empêcher l’accès)
    • config.xml (configuration de l’affichage des commentaires)
    • donnees.xml
  • [ Dossier ] js (les fichiers javascript)
  • .htaccess pour forcer l’utilisation de php5
  • afficher.php (affiche la page générale)
  • ecrire.php (script qui va écrire le commentaire)
  • liste.php (script qui va lister les commentaires)
  • index.html (pour empêcher le listing de fichiers)

>>> Téléchargement

Modèle de données

donnees.xml

Voici la XSD des messages. Le résultat au format XML dans le zip de téléchargement.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="commentaires">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" ref="commentaire"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="commentaire">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="auteur"/>
        <xs:element ref="mail"/>
        <xs:element ref="date"/>
        <xs:element ref="heure"/>
        <xs:element ref="ip"/>
        <xs:element ref="message"/>
        <xs:element ref="noteaccueil"/>
        <xs:element ref="notequalite"/>
        <xs:element ref="noteservice"/>
      </xs:sequence>
      <xs:attribute name="identifiant" use="required" type="xs:integer"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="auteur" type="xs:string"/>
  <xs:element name="mail" type="xs:string"/>
  <xs:element name="date" type="xs:NMTOKEN"/>
  <xs:element name="heure" type="xs:NMTOKEN"/>
  <xs:element name="ip" type="xs:NCName"/>
  <xs:element name="message" type="xs:string"/>
  <xs:element name="noteaccueil" type="xs:NMTOKEN"/>
  <xs:element name="notequalite" type="xs:NMTOKEN"/>
  <xs:element name="noteservice" type="xs:NMTOKEN"/>
</xs:schema>

Explications :

Globalement cela reste simple : un auteur, son mail, son adresse IP par mesure de précaution, les notes, le message et un identifiant… Rien de bien folichon quoi.

config.xml

Voici la XSD de la config. Le résultat au format XML dans le zip de téléchargement.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="config">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="nbmessages"/>
        <xs:element ref="dernierid"/>
        <xs:element ref="nbmessagesaffiche"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="nbmessages" type="xs:integer"/>
  <xs:element name="dernierid" type="xs:integer"/>
  <xs:element name="nbmessagesaffiche" type="xs:integer"/>
</xs:schema>

Explications :

Je dois peu-être m’expliquer sur un ou deux points : chaque message ayant un identifiant auto-incrémenté, il faut savoir quel a été le dernier Id de message enregistré. C’est là que la balise « dernierid » intervient. Il y a également un compteur de commentaire, une anticipation en cas de besoin.

la balise « nbmessageaffiche » quant à elle est une autre anticipation pour un futur module d’admin. Le script liste.php affichant les message est configuré pour prendre en compte ce paramètre : si nbmessageaffiche = 0 alors on ne limite pas le nombre de message affichés sur le site internet, si nbmessageaffiche ? 0 alors on limitera l’affiche à X messages où X sera le paramètre enregistré.



Lecture / Ecriture de données

Lecture

C’est le fichier « liste.php » qui établit la liste des commentaires. On utilisera SimpleXML pour le coup pour exploiter donnees.xml. Puis, pour accéder à chaque noeud il suffit de demander gentiment :

$bibliotheque = simplexml_load_file('donnees/donnees.xml');
$config = simplexml_load_file('donnees/config.xml');
$nbmessagesaffiche = $config->nbmessagesaffiche;
$nbmessages = $config->nbmessages;
//En revanche, PHP ne sait pas qu'on va faire des tests dessus comme avec un entier :
settype($nbmessagesaffiche , "integer");
settype($nbmessages , "integer");

On va ensuite pouvoir boucler en récupérant les données du fichier XML tout en les rangeant dans les bonnes cases :

foreach ($bibliotheque->commentaire as $commentaire) {
	if ($i++ > 0)
		echo'
		<div id="commentaire">
			<div id="commentairegauche">
				<div id="cadredetails">
					Par <span id="auteur">'.$commentaire->auteur.'</span>, le <span id="date">'.$commentaire->date.'</span> &#224; <span id="heure">'.$commentaire->heure.'</span>
				</div>
				<div id="cadremessage">
					<span id="message">'.$commentaire->message.'</span>
				</div>
			</div>
			<div id="commentairedroite">
				<div id="commentairenoteaccueil">
					<span>Accueil : '.$commentaire->noteaccueil.' /5</span>
				</div>
				<div id="commentairenotequalite">
					<span>Qualit&eacute; : '.$commentaire->notequalite.' /5</span>
				</div>
				<div id="commentairenoteservice">
					<span>Service : '.$commentaire->noteservice.' /5</span>
				</div>
			</div>
		</div>
		';
	}
}

Ecriture

C’est là le fichier ecrire.php qui rentre en jeu. On lui envoie en effet les champs à enregistrer. On va commencer par faire un test sur l’existance des champs, par sécurité :

if ( isset($_POST['code'])
	&& isset($_POST['verif'])
	&&isset($_POST['pseudo'])
	&& isset($_POST['email'])
	&& isset($_POST['comments'])
	&& isset($_POST['ip'])
	&& isset($_POST['code'])
	&& isset($_POST['noteaccueil'])
	&& isset($_POST['notequalite'])
	&& isset($_POST['noteservice']) )

Puis comme précédemment on va charger les fichiers XML pour les étudier

$bibliotheque = simplexml_load_file('donnees/donnees.xml');
$config = simplexml_load_file('donnees/config.xml');

D’abord le fichier de données pour voir si le message n’a pas déjà été posté (pour les enragés du double-clique), ensuite le fichier de paramétrage  afin de déterminer quel Id donner au nouveau commentaire (nombre de messages + 1). Ensuite, il faut incrémenter ces valeurs pour les ré enregistrer dans le fichier.

Dans tous les cas un code spécifique est renvoyé à la page appelante :

  • Code retour 0 si les champs n’existent pas (appel farfelu de la page ecrire.php)
  • Code retour -1 si le commentaire existe déjà
  • Code retour -2 si le captcha est mal saisi
  • Code retour 1 si tout s’est bien déroulé

Pour écrire dans le fichier XML c’est simple :

$newMessage = $bibliotheque->addChild('commentaire');

On rajoute un fils au fichier XML. Puis à ce fils, on donne un attribut

$newMessage->addAttribute('identifiant',$dernierid );

On donne à ce fils de nouveaux fils :

$newMessage->addchild('auteur',$_POST['pseudo'] ); //...etc.

Enfin, on écrit tout ça dans nos fichiers XML :

//On crée la nouvelle chaine XML pour la bibliothèque
$baseMiseAJour = $bibliotheque->asXML() ;
//et pour la config
$configMiseAJour = $config->asXML() ;
//On écrit la config
$fichierconf = fopen("donnees/config.xml","w");
fputs($fichierconf , $configMiseAJour ) ;
//et le nouveau message
$fichier = fopen("donnees/donnees.xml","w");
fputs($fichier , $baseMiseAJour ) ;

Voilà pour les différents scripts. Maintenant, voyons comment exploiter tout ça !



Structure HTML

Ici nous avons surtout les en-têtes HTML :

<head>
   <link rel="stylesheet" href="css/validationEngine.jquery.css" type="text/css" media="screen" title="no title" />
   <link rel="stylesheet" href="css/template.css" type="text/css" media="screen" title="no title" />
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   <script src="js/jquery.js" type="text/javascript"></script>
   <script src="js/jquery.validationEngine-fr.js" type="text/javascript"></script>
   <script src="js/jquery.validationEngine.js" type="text/javascript"></script>
   <script src="js/commentaires.js" type="text/javascript"></script>
</head>

Dans l’ordre : inclusion des feuilles de style, jquery, engin de validation et script maison. Rien à dire sur les premiers, mais nous reviendrons sur le dernier plus tard. En attendant, voici comment j’ai découpé ma page :

<div id="cadrecommentaires">
   <div id="listecommentaires">
      <div id="afficher">
      </div>
      <div id="confirmation">
         <div id="confirmationtexte">
         </div>
      </div>
   </div>
   <div id="lienAfficher">
      <span id="contenuLienAfficher"> > Ecrire un commentaire < </span>
   </div>
   <div id="ecrire">
      <!-- ICI LE FORMULAIRE -->
   </div>
</div>

En gros : un cadre pour afficher tous les commentaires mais également afficher la confirmation de l’ajout du commentaire (comme tout se fait en Ajax, pas de rechargement de page), un cadre avec un lien pour afficher la zone de saisie d’un commentaire et un dernier cadre pour ladite zone de saisie.

Pour ce qui est du formulaire, rien de sorcier. Si vous avez lu mon précédent billet sur le contrôleur de champs de formulaire, alors tout ira bien. Sinon, bonne lecture 🙂 La seule chose à noter c’est l’action du formulaire :

<form id="formID" method="post" action="javascript:envoyer();" onsubmit="">



Le javascript

Jusqu’à présent, on a vu les scripts de lecture/écriture, la page HTML… Mais le coeur du système reste le javascript. C’est en effet une série d’instruction javascript – JQuery pour être plus précis – qui va diriger l’orchestre.

Les routines

Nous avons embarqué un fichier javascript dans la page afficher.html : commentaires.js. Ce fichier contient avant tout ceci :

$(document).ready(function(){
	$.get("liste.php", function(data){
			$("#afficher").html(data);
		}
	);
	var affiche=false;
	$("#lienAfficher").click(function(){
		//$("#formID").fadeIn("slow");
		if(affiche == false){
			$("#formID").fadeIn("slow");
			affiche = true;
		}
		else{
			$("#formID").slideUp('slow');
			affiche = false;
		}
		$("html").animate({ scrollTop: $(document).height() }, "slow");
		return false;
	});
});

la première partie sert à afficher les commentaire dans le div #afficher. Oui oui, grâce à JQuery une petite ligne permet d’appeler un script php et d’en afficher le retour dynamiquement dans le corps de la page : c’est l’Ajax !

En gros ce qu’il se passe, c’est que le script php fait afficher des choses à l’aide de la fonction « echo » (en l’occurrence la structure HTML et le contenu des commentaires). Ce qui est affiché est retourné à l’appel de la fonction get() puis fourré dans la variable « data ». Il suffit ensuite d’afficher, au retour de l’appel de liste.php d’effectuer les opérations que l’on souhaite dans la function(data) prévue à cet effet. Ici, ce que l’on souhaite, c’est mettre le contenu de « data » dans le div #afficher.

Le reste des routines consiste juste à surveiller le clique sur le lien « Ecrire un commentaire », clique qui affiche le formulaire de saisie avec un effet d’ouverture / fermeture sympa et un scroll automatique vers la première zone de saisie.

L’écriture

La dernière partie c’est l’écriture. Cela reste pourtant simple avec JQuery. Le tout est de savoir qu’on peut réaliser un appel à un script php en lui passant des paramètres :

$.post("ecrire.php", {captcha:$("#code").val(), verif:$("#verif").val()}, function(data){ /*ce que l'on veut*/ } );

le reste, c’est juste du traitement de codes retours :

if (data == "-1"){
	$("#confirmationtexte").css({'display': 'none'});
	$("#confirmationtexte").html("Votre message a d&eacute;j&#224; &eacute;t&eacute; ajout&eacute;.
Merci de votre commentaire.");
	$("#confirmationtexte").css({'background': '#DBAAA3'});
	$("#confirmationtexte").fadeIn('slow');
}

Voilà, c’est terminé… N’hésitez pas à contribuer si vous pensez que ce petit projet a le mérite d’exister voire de continuer !

11 commentaires

  1. Bonjour,

    Je développe mon site web moi-même et j’apprends le HTML/CSS/PHP etc… au fur et à mesure de mes besoins. Je viens de découvrir les possibilités des plugins JQuery et j’étais ravie de trouver votre module de commentaires.
    Mais voilà, je ne suis pas encore (du tout) au point sur tout, et j’ai scrupuleusement suivi toutes les instructions, mais ça ne marche pas, le lien sur « Envoyer le Message » dans ma page web ne fonctionne pas.
    A bien y regarder, il me semble qu’il faut créer un formulaire ? Je ne l’ai encore jamais fait et je ne sais pas faire. J’y étais presque !
    Merci de votre aide…

    1. Bonjour,
      Attention aux confusions, ce module n’est pas un plugin javascript mais bien un module en standalone. Son pobjectif est plus d’attaquer certaines problématiques voire de prendre connaissance de technologies. Il faut bien entendu quelques notions relativement avancées pour pouvoir se l’approprier.
      Du coup oui, en effet, il faut préparer un formulaire pour recevoir les commentaires et notes, mais c’est détaillé dans le code source en principe. Cela dit une nouvelle fois, il faut prendre garde au caractère ludique plus que fonctionnel de ce module 🙂

        1. Bonjour,
          C’est le but de l’article et du zip à télécharger.
          Il ne s’agit pas ici d’apprendre à développer, mais de partager l’expérience de la réalisation d’un moule de commentaire. Ce partage se base sur le postulat que les lecteurs possèdent les bases nécessaires. Si ce n’est pas le cas, alors il n’est pas judicieux de commencer par ça.

  2. Merci pour ce tutoriel qui va me permettre enfin (je l’espère) de mettre en place un système de dédicace « instantané. »

    J’ai tout mis en place sur ma page web en ne gardant que les champs pseudo (auteur) et message. La dédicace que j’ai entrée dans le fichier données.xml s’affiche, à savoir :

    NULL
    NULL

    qui donne, suivant ma structure, la dédicace : « NULL par NULL »

    Cependant, quand j’utilise le formulaire pour remplacer cette dédicace par une autre… Je valide mais il ne se passe rien.

    A votre avis, quel type d’erreur pourrait causer un tel dysfonctionnement ? Dans quel fichier aurais-je pu faire une erreur ? Je peux vous fournir les fichiers si vous voulez bien m’aider
    plus précisément.

    Je vous remercie de votre aide
    gmarcilly

  3. Quelqu’un peut-il m’aider a intégrer un module commentaire sur mon site car je ne comprend rien au php et autre!! help me please c’est urgent

    1. Bonjour,
      Sans connaitre le php, il parait difficile d’intégrer un module de commentaire sur ton site.
      Le mieux que je puisse te recommander, c’est de t’installer un wordpress ou tout autre CMS du genre. Cette fonctionnailté y est par essence incluse.
      Bonne chance!

  4. Merci pour votre commentaire!

    Dans le modèle de données figurent @IP et heure de post de message. Un moyen d’éviter le spam serait de refuser le commentaire si un autre commentaire de la même IP a déjà été déposé dans l’heure passée.

    Je ne l’ai pas implémentée moi-même, mais avait anticipé le modèle de données en conséquence dans le cas où.

    Si vous rencontrez des difficultés, je serais ravis d’un échange d’informations sur ces méthodes et de vous filer un coup de main.

  5. Bonjour, Superbe article, j’étais à la recherche de ce genre de module qui est l’un des mieux que j’ai trouvé, ou le faire moi même avec une base de données que je pourrais gérer via mon back office, mais comme je n’ai pas trop l’habitude des fichiers XML je me demande comment je vais pouvoir faire une page admin pour la gestion des messages? Toutefois je le fais déjà avec mon module de Flux que j’ai fait moi même, je vais voir cela, car votre module permet d’éviter le post de message intempestif mais malheureusement peut être pas le spam. Quoi que ! Merci

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *