Accueil > ajax > systeme-commentaire-ajax

{ Système de commentaire ajax / php / mysql }

Introduction

Comme vous avez déjà peut-être pu le constater, un nouveau module de commentaire basé sur la technologie AJAX est venu s'ajouter à Astuces-Webmaster. Et c'est précisement ce module de commentaire que je vais vous apprendre à intégrer dans un site web. Mais tout d'abord, je vais vous présenter les deux modules qui font la force de ce module de commentaire.

1. Le premier élément est la base du système de commentaire AJAXisé et tiré de l'excellent site anglophone Tutorialzine.com et constitue ainsi la base du module, robuste et fiable.

2. Quant au deuxième, le défi était de trouvé un formulaire qui donne envie de laisser des commentaires ! Quelque chose de moderne, exploitant les nouvelles propriétés CSS3 et qui ait de la gueule ! Second paramètre requis : la simplicité, la clareté et l'intuitivité du formulaire. Gros challenge vous dites ? Je dois avouer qu'effectivement j'ai mis un certain temps à le trouver, mais j'ai fini par mettre la main sur quelque chose de très convainquant et qui remplissait les conditions fixées au départ. Je n'en dis pas plus, je vous laisse voir de quoi il s'agit.

Système de commentaire basé sur AJAX

plus

formulaire pure CSS3

plus

apercu du système de commentaire AW

Et voilà le résultat ! Un superbe module de commentaire qui en jette un max. ! Sans plus attendre je vous laisse checker une démo de cette petite merveille, le tutoriel est juste en dessous.

Avantages

Pas de rechargement de la page lors du post des commentaires grâce à son moteur AJAX

Formulaire intuitif et parfaitement comprhénsible (pas de subitilité cachée)

Le bouton "Envoyer" affiche un message pendant l'envoi du commentaire indiquant ainsi à l'utilisateur que sa requête est en cours de traitement.

Protection contre les posts intempestifs

Inconvénients

Pas de rechargement de la page lors du post des commentaires grâce à son moteur AJAX

Formulaire intuitif et parfaitement comprhénsible (pas de subitilité cachée

Le bouton "Envoyer" affiche un message pendant l'envoi du commentaire indiquant ainsi à l'utilisateur que sa requête est en cours de traitement.

Protection contre les posts intempestifs

Création de la table dans mysql

CREATE TABLE `comments` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(128) NOT NULL default '',
`url` varchar(255) NOT NULL default '',
`email` varchar(255) NOT NULL default '',
`body` text NOT NULL,
`dt` timestamp NOT NULL,
`page_id` varchar(128) NOT NULL default '0',
PRIMARY KEY  (`id`)
) TYPE=MyISAM  AUTO_INCREMENT=154 ;

Connexion à la base de données

<?php
  
  /* Configuration de la connexion */
  
  $db_host		= 'localhost';
  $db_user		= 'root';
  $db_pass		= 'toor';
  $db_database	= 'database'; 
 
  /* Création de la connexion */
  $link = @mysql_connect($db_host,$db_user,$db_pass) or die('Unable to establish a DB connection');
  
  mysql_query("SET NAMES 'utf8'");
  mysql_select_db($db_database,$link);
?>

Récupération des commentaires & structure du formu

<?php 

 // Error reporting:
 error_reporting(E_ALL^E_NOTICE);

 include "../comm/connect.php";
 include "../comm/comment.class.php";

 /*
 / On récupère les commentaires s'il y en a dans la BDD
 */

 $comments = array();
 $result = mysql_query("SELECT * FROM comments WHERE page_id = '$id_page' ORDER BY id ASC");

 while($row = mysql_fetch_assoc($result))
 {
	$comments[] = new Comment($row);
 }

 /*
 / Affichage des commentaires un par un
 */

 foreach($comments as $c){
	echo $c->markup();
 }

 ?>
 <div id="addCommentContainer">
 <h4 align="center">Ajouter un commentaire</h4>
 <form id="form1" method="post" action="">
 <p>
 <label for="name">Nom</label>
 <input name="name" type="text" id="name" size="45" />
 </p>
 <p>
 <label for="email">Email</label>
 <input name="email" type="text" id="email" size="45" />
 </p>
 <p>
 <label for="commentaires">Commentaire</label>
 <textarea name="body" cols="35" rows="6" id="body"></textarea>
 </p>
 <p>
 <label for="url">Site (facultatif)</label>
 <input name="url" type="text" id="url" size="45" /></p>
 <input type="hidden" name="id_page" id="id_page" value="<?php echo $id_page ?>" />
 <p><input type="submit" id="submit" value="Envoyer" /></p>

 </form>
 </div>

Traitement des données et vérification

<?php

 class Comment
 {
	private $data = array();
	public function __construct($row)
	{
		 /*
		 / Le constructeur
		 */
		 $this->data = $row;
	}

	public function markup()
	{
		/*
		/ This method outputs the XHTML markup of the comment
		*/

		// Setting up an alias, so we don't have to write $this->data every time:
		$d = &$this->data;

		$link_open = '';
		$link_close = '';

		if($d['url']){
			// If the person has entered a URL when adding a comment,
			// define opening and closing hyperlink tags
			$link_open = '<a href="'.$d['url'].'">';
			$link_close = '</a>';
		}

		// Converting the time to a UNIX timestamp:
		$d['dt'] = strtotime($d['dt']);
		
		// Needed for the default gravatar image:
		$url = 'http://'.dirname($_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"]).'/comm/img/default_avatar.gif';

		return '<div class="comment">
		 <div class="avatar">
		 '.$link_open.'
		 <img src="http://www.gravatar.com/avatar/'.md5($d['email']).'?size=50&amp;default='.urlencode($url).'" />
		 '.$link_close.'
		 </div>

		 <div class="name">'.$link_open.$d['name'].$link_close.'</div>
		 <div class="date" title="Added at '.date('H:i on d M Y',$d['dt']).'">'.date('d M Y',$d['dt']).'</div>
		 <p>'.$d['body'].'</p>
		 </div>
		 ';
	}

	public static function validate(&$arr)
	{
		/*
		/ This method is used to validate the data sent via AJAX.
		/
		/ It return true/false depending on whether the data is valid, and populates
		/ the $arr array passed as a paremter (notice the ampersand above) with
		/ either the valid input data, or the error messages.
		*/

		$errors = array();
		$data = array();

		// Using the filter_input function introduced in PHP 5.2.0

		if(!($data['id_page'] = filter_input(INPUT_POST,'id_page',FILTER_CALLBACK,array('options'=>'Comment::validate_text'))))
		{
			$errors['id_page'] = '*';
		}

		if(!($data['email'] = filter_input(INPUT_POST,'email',FILTER_VALIDATE_EMAIL)))
		{
			$errors['email'] = '<span style="color:red;"> Adresse invalide</span>';
		}

		if(!($data['url'] = filter_input(INPUT_POST,'url',FILTER_VALIDATE_URL)))
		{
			// If the URL field was not populated with a valid URL,
			// act as if no URL was entered at all:
			$url = '';
		}

		// Utilisation d'un filtre personnalisé callback function
		if(!($data['body'] = filter_input(INPUT_POST,'body',FILTER_CALLBACK,array('options'=>'Comment::validate_text'))))
		{
			$errors['body'] = '<span style="color:red;"> Entrez un commentaire</span>';
		}

		if(!($data['name'] = filter_input(INPUT_POST,'name',FILTER_CALLBACK,array('options'=>'Comment::validate_text'))))
		{
			$errors['name'] = '<span style="color:red;"> Nom manquant</span>';
		}

		if(!empty($errors)){
			// s'il y des erreurs : on les copie dans $errors array à $arr
			$arr = $errors;
			return false;
		}

		// si les données sont valides, on nettoie le code HTML et on les copie dans $arr
		foreach($data as $k=>$v){
			$arr[$k] = mysql_real_escape_string($v);
		}

		// On s'assure que l'adresse email est bien en minuscule
		$arr['email'] = strtolower(trim($arr['email']));
		return true;
	}

	private static function validate_text($str)
	{
		/*
		/ La méthode utilisée pour le filtre des champs FILTER_CALLBACK
		*/

		if(mb_strlen($str,'utf8')<1)
		return false;

		// Encoder les caractères spéciaux tel que (<, >, ", & .. etc) et les convertir
		// Modifier les nouvelles lignes par la balise <br>
		$str = nl2br(htmlspecialchars($str));

		// Enlever les lignes inutiles
		$str = str_replace(array(chr(10),chr(13)),'',$str);
		return $str;
	}
}
 ?>

Envoi des données dans la bdd

<?php
// Error reporting:
error_reporting(E_ALL^E_NOTICE);

include "connect.php";
include "comment.class.php";

$arr = array();
$validates = Comment::validate($arr);

if($validates)
{
	/* Tout est Ok, insertion dans la BDD */

	mysql_query("INSERT INTO comments(name,url,email,body,page_id)
	VALUES (
	'".$arr['name']."',
	'".$arr['url']."',
	'".$arr['email']."',
	'".$arr['body']."',
	'".$arr['id_page']."'
	)");

	$arr['dt'] = date('r',time());
	$arr['id'] = mysql_insert_id();

	/* Fonction mail pour être prévenu lors de l'ajout d'un nouveau commentair */

	$msg = "Un nouveau commentaire a été ajouté sur Astuces-Webmaster.ch! 
	Nom : ".$arr['name']."
	Email : ".$arr['email'].";
	Page = ".$arr['id_page'].";
	Commentaire = ".$arr['body'];

	mail('votre-email@email.com','Nouveau commentaire',$msg);

	$arr = array_map('stripslashes',$arr);

	$insertedComment = new Comment($arr);

	/* Interprétation du HTML */

	echo json_encode(array('status'=>1,'html'=>$insertedComment->markup()));
}
else
{
	/* Affichage des messages d'erreurs */
	echo '{"status":0,"errors":'.json_encode($arr).'}';
}
?>

Ajax

Le fichier script.js contient le coeur de la fonction AJAX qui va permettre d'afficher un commentaire fraichement rédigé directement en dessous des autres sans avoir à rechargé toute la page. C'est le deuxième plus gros atout de ce module de commentaire.

{

Note du chef : la fonction jQuery.noConflict(); a été ajouté dans le script et la variable générale (habituellement $) a été changée pour $j ce afin d'éviter les conflits avec d'éventuels autres bibliothèques Javascript qui serait installé sur votre site.

}
$j = jQuery.noConflict();

$j(function() {

	/* Le code qui suit est exécuté une fois que le DOM est chargé */
	
	/* cette variable empêche les posts intempestifs */
	var working = false;

	/* On récupère les événements du bouton submit */
	$j('#form1').submit(function(e){

		e.preventDefault();
		if(working) return false;

		working = true;
		$j('#submit').val('Chargement en cours..');
		$j('span.error').remove();

		/* Envoi des données au fichier submit.php */
		$j.post('../comm/submit.php',$j(this).serialize(),function(msg){

			working = false;
			$j('#submit').val('Submit');

			if(msg.status){

				/* 
				/ Si l'insertion du commentaire c'est bien passé
				/ l'afficher en dessous des autres avec un effet SlideDown
				/*/

				$j(msg.html).hide().insertBefore('#addCommentContainer').slideDown();
				$j('#body').val('');
			}
			else {

				$j.each(msg.errors,function(k,v){
					$j('label[for='+k+']').append('<span class="error">'+v+'</span>');
				});
			}
		},'json');
	});
});

La couche css3 ;-)

/* MODULE DE COMMENTAIRE AJAX */

 .comment,
 #addCommentContainer{
 background:#f7f7f7;
 background:-moz-linear-gradient(90deg, #ccc, #fff); /* Firefox */
 background:-webkit-gradient(linear, left top, left bottom, from(#fff), to(#ccc)); /* Webkit */
 border:1px solid #aaa;
 border-radius:10px;
 -moz-border-radius:10px;
 -webkit-border-radius:10px;
 -moz-box-shadow:0 0 15px #aaa;
 -webkit-box-shadow:0 0 15px #aaa;
 box-shadow:0 0 15px #aaa;
 margin:20px auto;
 padding:20px;
 width:510px;
 }

 .comment .avatar{
 height:50px;
 width:50px;
 background:url('../comm/img/default_avatar.gif') no-repeat #fcfcfc;
 -moz-box-shadow:1px 1px 0 #c2c2c2;
 -webkit-box-shadow:1px 1px 0 #c2c2c2;
 box-shadow:1px 1px 0 #c2c2c2;
 float:left;
 margin-right: 20px;
 }

 .comment .avatar img{
 display:block;
 }

 .comment .name{
 padding-bottom:10px;
 font-size:14px;
 color:#0459b7;
 font-weight: bold;
 }

 .comment .date{
 font-size:10px;
 padding: 20px 10px 0 10px;
 color:#666;
 float: right;
 }

 .comment p,
 #addCommentContainer p{
 line-height:1.5;
 overflow-x:hidden;
 }

 fieldset,img{ border:0;}

 html {
 overflow:-moz-scrollbars-vertical;
 }

 form {
 margin: 20px 0;
 }

 #comDiplayBox{
 background:#f7f7f7;
 background:-moz-linear-gradient(90deg, #ccc, #fff); /* Firefox */
 background:-webkit-gradient(linear, left top, left bottom, from(#fff), to(#ccc)); /* Webkit */
 border:1px solid #aaa;
 -moz-border-radius:10px;
 -webkit-border-radius:10px;
 border-radius:10px;
 -moz-box-shadow:0 0 15px #aaa;
 -webkit-box-shadow:0 0 15px #aaa;
 box-shadow:0 0 15px #aaa;
 margin:20px auto 0;
 padding:20px;
 width:510px;
 height: auto;
 }

 form p{
 margin-bottom:20px;
 }

 form p:last-child{ /* Sélecteur avancé pour sélectionner le dernier paragraphe du formulaire */
 margin-bottom:0;
 }

 label{
 cursor:pointer;
 display:block;
 float:left;
 font-weight:bold;
 letter-spacing: 1px;
 line-height:28px;
 margin-bottom:5px;
 width:160px;
 }

 form p:hover label{
 color:#0459b7;
 }

 form p:hover label:after{
 content:' >>';
 }

 input[type=text], textarea,
 input[type=password]{
 background: rgba(255, 255, 255, 0.9);
 background:-moz-linear-gradient(90deg, #fff, #eee); /* Firefox */
 background:-webkit-gradient(linear, left top, left bottom, from(#eee), to(#fff), color-stop(0.2, #fff)); /* Webkit */
 border:1px solid #aaa;
 border-radius:3px;
 -moz-border-radius:3px;
 -webkit-border-radius:3px;
 -moz-box-shadow:0 0 3px #aaa;
 -webkit-box-shadow:0 0 3px #aaa;
 box-shadow:0 0 3px #aaa;
 padding:5px;
 }

 input[type=text]:focus, textarea:focus,
 input[type=password]:focus{
 border-color:#093c75;
 box-shadow:0 0 3px #0459b7;
 -moz-box-shadow:0 0 3px #0459b7;
 -webkit-box-shadow:0 0 3px #0459b7;
 outline:none; /* Pour enlever le contour jaune lorsque l'on sélectionne un input dans Chrome */
 }

 select{
 cursor:pointer;
 padding:3px;
 box-shadow:0 0 3px #0459b7;
 -moz-box-shadow:0 0 3px #aaa;
 -webkit-box-shadow:0 0 3px #aaa;
 }

 select:active,
 select:focus{
 border:1px solid #093c75;
 box-shadow:0 0 3px #0459b7;
 -moz-box-shadow:0 0 3px #0459b7;
 -webkit-box-shadow:0 0 3px #0459b7;
 outline:none;
 }

 input[type=submit],
 a.submit{
 background:#ddd;
 background:-moz-linear-gradient(90deg, #0459b7, #08adff); /* Firefox */
 background:-webkit-gradient(linear, left top, left bottom, from(#08adff), to(#0459b7)); /* Webkit */
 border:1px solid #093c75;
 border-radius:3px;
 -moz-border-radius:3px;
 -webkit-border-radius:3px;
 box-shadow:0 1px 0 #fff;
 -moz-box-shadow:0 1px 0 #fff;
 -webkit-box-shadow:0 1px 0 #fff;
 color:#fff;
 cursor:pointer;
 font-weight:bold;
 margin-left:225px;
 padding:5px 10px;
 text-decoration:none;
 text-shadow:0 1px 1px #333;
 text-transform:uppercase;
 }

 input[type=submit]:hover,
 a.submit:hover{
 background:#eee;
 background:-moz-linear-gradient(90deg, #067cd3, #0bcdff);
 background:-webkit-gradient(linear, left top, left bottom, from(#0bcdff), to(#067cd3));
 border-color:#093c75;
 text-decoration:none;
 }

 input[type=submit]:active,
 input[type=submit]:focus,
 a.submit:active,
 a.submit:focus{
 background:#ccc;
 background:-moz-linear-gradient(90deg, #0bcdff, #067cd3);
 background:-webkit-gradient(linear, left top, left bottom, from(#067cd3), to(#0bcdff));
 border-color:#093c75;
 outline:none;
 }
 

Votre module de commentaire AJAX / PHP devrait être operationel ! Vous avez une démo ici.