AJAX en clair

JPBruneau

Tutoriel Ajax en clair - Comment réaliser un chat complet en AJAX

Cet article vous permettra de mieux appréhender la technique de l'AJAX et ce de manière ludique.
Commentez

- Titre : AJAX en clair

- Auteur : JPBruneau

- Parution : 29 janvier 2013

- Mise à jour : 29 mai 2013

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2012 JPBruneau. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Avant-propos

- II. Prérequis

- III. Dans cet article

- IV. Le code AJAX

- V. Le chat

- V-A. Mise en place

- V-B. La partie AJAX

- V-C. La partie chat

- V-D. Le serveur

- VI. Sources

- VII. Remerciements

I - Avant-propos

Nous attirons votre attention sur le fait que tous les fichiers PHP, CSS et SQL sont écrits en UTF-8 sans BOM (Byte Order Mark), permettant ainsi d'utiliser les symboles comme Euro, etc.

Le codage UTF-8 « standard », donc avec BOM, ajoute un caractère en début de fichier. C'est un espace insécable de largeur nulle « zero-width no-break space ». Ce caractère est invisible pour l'utilisateur. En fait, ce caractère n'a pas d'intérêt en UTF-8. Il est utile en UTF-16 ou UTF-32.

Le fait de laisser le BOM en tête de fichier envoie un header au HTML du visiteur qui empêche donc par exemple de faire un session_start() par la suite.

S'adressant à tous ceux qui maîtrisent la « programmation permettant de gérer un site Web », cet article a pour but de vous mettre en main, très facilement, un outil pour dynamiser vos pages Web grâce à l'emploi d'AJAX.

Developpez.com possède déjà un grand nombre de tutoriels et d'articles sur cette méthode AJAX. Le présent article n'a donc pour but que de vous apporter un éclairage sur le mécanisme de base d'AJAX, espérant ainsi vous permettre de dévorer bien plus facilement la totalité de nos formations et articles.

Il faut préciser qu'AJAX n'est en rien associé au PHP et encore moins au SQL. C'est uniquement notre exemple qui les utilise. Vous pourriez traiter directement un fichier texte ou un XML. Du reste, il s'agit de la vocation d'origine d'AJAX.

II - Prérequis

Bon programmeur comme vous l'êtes, vous savez faire un formulaire appelant une page PHP qui analysera les éléments saisis, exécutera des tâches en fonction des saisies, traitera toute la logique PHP et les actions SQL si besoin, puis qui proposera une nouvelle page HTML ou appellera un autre fichier PHP.

III - Dans cet article

Si vous dominez ce mécanisme, alors vous allez faire un très grand pas en AJAX. En effet, AJAX est un petit code JavaScript qui envoie en POST ou en GET tout élément venant d'une page HTML vers un fichier PHP du serveur (dans l'exemple que nous avons choisi). Et ce comme le ferait un simple formulaire tout en conservant la page HTML active chez votre visiteur.

Le « premier grand plus » est que ce mini-code peut envoyer les éléments (données saisies) d'un formulaire, mais également des événements de la page HTML et des paramètres de notre choix ! Un ordre qui peut être minuté par un setTimeout(), etc.

AJAX signifie Asynchronous Javascript And XML. Ce qui veut dire qu'AJAX traite de base les flux XML de façon asynchrone. Notre article ne traitera que des liaisons HTML/Javascript AJAX côté client (visiteur) appelant un fichier PHP pour un traitement côté serveur, lequel utilisera entre autres MySQL. La transaction sera asynchrone, mais elle pourrait être synchrone. C'est une option à paramétrer.

Nous avons choisi ceci parce que cette façon d'utiliser AJAX vous ouvrira 90 % des possibilités de ce type de page dynamique. De plus, redisons que tout autre mode (en particulier XML) est largement expliqué dans d'autres articles du site.

Ce mini-code AJAX est loin de se contenter de préserver votre page HTML et d'envoyer des POST ou GET à un fichier PHP du serveur. Il est capable de recevoir une réponse, par exemple un echo du PHP appelé et d'analyser cette réponse. Puis d'afficher le résultat dans la page HTML.

Vous y êtes, c'est aussi simple que cela. Une page HTML qui change dynamiquement sans se recharger. Alors, à vous d'imaginer à quoi cela peut vous servir.

Maintenant, nous allons donc décortiquer ce tout petit module JavaScript de quelques lignes qui fait tant de merveilles, puis nous l'appliquerons à une application simple... un chat !

IV - Le code AJAX

Vous trouverez plusieurs versions de ce code sur le Web et dans nos articles, mais ne vous inquiétez pas, ils utilisent tous le même moteur !

function maFonctionAjax(unParametre,action)
{
var MonAjax;
if (window.XMLHttpRequest)
{
// Mozilla, Safari, ...
MonAjax = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
// IE
MonAjax = new ActiveXObject('Microsoft.XMLHTTP');
}
else
{
alert("Votre navigateur n'est pas adapté pour faire des requêtes AJAX...");
MonAjax = false;
}

MonAjax.open('POST',"a.php",true);

MonAjax.onreadystatechange = function()
{
if (MonAjax.readyState == 4 && MonAjax.status == 200)
{
if(action=="fait1") { document.getElementById('LeRetour1').innerHTML = MonAjax.responseText;}
if(action=="fait2") { document.getElementById('LeRetour2').innerHTML = MonAjax.responseText;}
}
}

MonAjax.setRequestHeader('Content-type','application/x-www-form-urlencoded');
MonAjax.send('unParametre='+unParametre+'&action='+action);
}

Oh que c'est simple. Voilà qui mérite tout de même une explication ligne par ligne. Ainsi, vous saurez TOUT sur l'AJAX.

J'aimerais simplement vous faire remarquer que de nombreuses pages en AJAX sont réalisées avec un framework JavaScript proposant une version simplifiée de l'AJAX. Sachez juste qu'en réalité ces « usines à gaz », bien pratiques par ailleurs, ne font qu'utiliser strictement ce mini-code. Du reste, si vous lisez cet article c'est justement parce que vous voulez savoir comment cela fonctionne en réalité.

Donc vous avez une page HTML et vous voulez lui ajouter une fonction AJAX pour afficher un texte dans une div ou dans une autre. Dans votre JavaScript, il vous suffit d'ajouter la fonction que nous avons appelée maFonctionAjax.

Tiens, c'est écrit function maFonctionAjax(unParametre,action). En effet, dans notre cas nous appellerons cette fonction chaque fois que nous voudrons afficher le résultat d'une requête SQL sur l'id unParametre et que nous attendons le résultat dans une div selon la valeur fait1 ou fait2 qui est représentée par action. Voilà, nous sommes dans la fonction avec nos deux paramètres. En premier lieu, nous allons déclarer un pointeur qui va devenir essentiel. Ce sera notre pointeur AJAX.

var MonAjax;

Tout est prêt pour initialiser le moteur AJAX. Pour cela nous allons voir sous quelle forme nous l'appelons en tenant compte du navigateur. Fidèles à l'esprit de cet article, nous le faisons sous une forme simplifiée qui convient à tout navigateur de dernière génération.

if (window.XMLHttpRequest)
{
// Mozilla, Safari...
MonAjax = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
// IE
MonAjax = new ActiveXObject('Microsoft.XMLHTTP');
}
else
{
alert("Votre navigateur n'est pas adapté pour faire des requêtes AJAX...");
MonAjax = false;
}

Avec ce code, nous initialisons MonAjax. Tout est déjà prêt à l'emploi. Vous admettrez que ce n'était pas sorcier !

C'est le moment de préciser quelques points sur la fonction XMLHttpRequest. Un bijou capable d'envoyer une requête à un serveur et de recevoir une réponse. À l'origine c'est Microsoft qui avait lancé cette méthode avec un ActiveX nommé XMLHTTP. Il est depuis bien longtemps inclus dans Oulook Express. Les grands navigateurs, à l'apparition d'AJAX, ont créé leurs propres fonctions XMLHttpRequest. C'est le cas de FireFox, Opera, Google Chrome, Safari, etc. Ne cherchant uniquement qu'à être homogène avec ses concurrents, Microsoft a alors inclus la compatibilité proposée par le WC3 en introduisant XMLHttpRequest depuis IE7.

Reste à exploiter notre cas particulier avec le code suivant où nous ouvrons le dialogue avec le fichier a.php du serveur en lui précisant qu'il va recevoir du POST. true indique au moteur que nous sommes en mode asynchrone. C'est-à-dire que le JavaScript poursuit son travail en parallèle de la requête AJAX. Il n'attend pas la réponse qui arrivera plus tard.

Nous pouvons réaliser notre réception de la réponse par Requete.responseText (c'est notre cas) ou par Requete.responseXML. Ces propriétés nous permettent de savoir comment considérer la réponse. Avec Requete.responseText, nous traiterons du texte. Avec Requete.responseXML, nous traiterons un document XML. Nous avons opté pour une réponse sous forme d'echo depuis notre fichier PHP. Cela aurait bien entendu pu être un fichier texte. Nous aurions alors écrit MonAjax.open(« GET », « http:www.monsite/unfichier.txt », true);.

MonAjax.open('POST',"a.php",true);
MonAjax.onreadystatechange = function()
{
/*  onreadystatechange alerte le JavaScript qu'une réponse est arrivée du serveur */
if (MonAjax.readyState == 4 && MonAjax.status == 200)
{
if(action=="fait1") { document.getElementById('LeRetour1').innerHTML = MonAjax.responseText;}
if(action=="fait2") { document.getElementById('LeRetour2').innerHTML = MonAjax.responseText;}
}
}

MonAjax.setRequestHeader('Content-type','application/x-www-form-urlencoded');
MonAjax.send('unParametre='+unParametre+'&action='+action);

Les statuts (état de la requête) permettent de suivre l'évolution de la requête. Tenons compte des statuts qui nous intéressent dans le onreadystatechange. Voici les valeurs possibles pour le readyState :

- 0 : non envoyé, open() n'a pas encore été appelée ;

- 1 : ouvert, send() n'a pas encore été appelée ;

- 2 : headers reçus, send() a été appelée, les headers et les statuts sont disponibles ;

- 3 : chargement, responseText contient des données partielles ;

- 4 : OK, l'opération est terminée.

Donc seul le « 4 » nous intéresse !

Pour status, nous nous attendons à recevoir la réponse « 200 » qui signifie qu'il n'y a eu aucune erreur de protocole. Lorsque nous recevons la réponse, si les status sont bons, alors nous écrivons MonAjax.responseText dans la div précisée par action comme nous l'avons expliqué.

Il me reste à vous dire que le fichier a.php appelé lors de la requête AJAX est strictement identique à tout autre fichier PHP. Il peut, avec les paramètres reçus, traiter du SQL et préparer un texte en guise de réponse. Puis, il peut se terminer par un echo. Celui qui doit être envoyé, celui qui contiendra la réponse ! Ainsi, nous recevons souvent des noms de pseudo, des mises en page HTML, des textes, etc. tout cela concaténé sur un seul echo !

Dernière précision au sujet du fichier PHP, il faudra bien sûr lui donner son encodage en tête de fichier :

<?php
header('Content-type: text/HTML; charset=UTF-8');
//etc.
?>

Tous les codes AJAX utilisent en fait ce moteur. Mais selon la complexité de notre besoin, la page HTML a souvent plusieurs de ses éléments qui sollicitent cette fonction AJAX. Alors, devons-nous en faire des copies ? NON NON... Comme beaucoup de langages (à commencer par le « C ») chaque appel d'une fonction crée en mémoire une copie de celle-ci ! Donc, non seulement le code AJAX est une toute petite fonction, mais sa seule présence permet des combinaisons de requêtes complexes.

V - Le chat

Pour illustrer ceci, nous avons choisi de faire un chat d'environ 250 lignes de code.

- Chaque pseudo aura un avatar.

- La discussion sera réaffichée régulièrement.

- La liste des pseudos en ligne sera affichée.

- Une zone de saisie est bien sûr prévue pour participer au chat.

- Un GIF animé d'attente nous indiquera toute action en cours non terminée.

Par contre, afin de soulager ce code, la mise en page sera sommaire. L'affichage du chat lui-même est total (pas de gestion de pagination) car le but est simplement de mettre en pratique des requêtes AJAX.

V-A - Mise en place

Voici les matériaux du chat. Un premier zip contient tout le répertoire ../ajax/. Vous le trouverez ici. http://www.fox-infographie.com/forum/ajax.zip

Il s'agit essentiellement d'images servant à améliorer l'aspect du chat. Cependant, vous y trouverez également ajax_tchat.sql qu'il vous suffira d'importer à l'aide de votre cher PHPMYADMIN dans votre SQL. Ceci vous permettra de voir la structure des deux tables utilisées. Tout le reste du zip doit être placé dans ../ajax/.

Un deuxième zip contient les fichiers de la racine du site. Vous le trouverez ici. http://www.fox-infographie.com/forum/tchat.zip

Il contient :

- ajax.css : la feuille de style du site, inutile de commenter ; ;-)

- index.php : l'index (vide) du site ;

- ajax.php : sert au lancement du chat (login) ;

- ajax_tchat_page.php : génère la page HTML du chat et donc contient notre « moteur AJAX » ;

- ajax_tchat_pdo.php : le PHP du serveur qui sera appelé par le code AJAX ;

- ajax_sql.php : un include contenant le login SQL/PDO et le DOCTYPE des fichiers HTML.

V-B - La partie AJAX

Donc tout commence par le fichier ajax.php. Ce fichier est le vrai lancement du chat, c'est l'identification. Ce code devrait gérer un login complet, mais nous l'avons simplifié ici uniquement pour pouvoir tester. À vous de faire un vrai login comme pour un forum ou n'importe quelle autre zone protégée. Cependant, se trouve dans ce code un point important du chat, l'auto-déconnexion du visiteur. Ainsi, si le chat est sur un site Web et que je choisis le pseudo christele, vous ne pourrez plus l'utiliser. Par contre, dès que je quitte la page, vous pouvez vous loguer en tant que christele ! Ceci permet de ne pas avoir plusieurs personnes connectées avec le même pseudo. C'est cette partie du code qui gère cela :

if($row["ip"] == $_SERVER["REMOTE_ADDR"] && time()-$row["date"]<60 )
{
$ActuPseudoID = $row["id"];
}
else if (time()-$row["date"]>60)
{
$ActuPseudoID =  $row["id"];
}
else
{
$erreur = "Ce pseudo est déjà en cours d'utilisation";
}

Vous verrez plus loin dans l'analyse de ajax_tchat_pdo.php que tant qu'un visiteur poste des messages, il est « rafraichi » au niveau de son login.

<?php
session_start();
header('Content-type: text/html; charset=UTF8');
$moiChri="O";
require("ajax_sql.php");
$pseudo = (isset($_POST['pseudo'])) ? secur($_POST['pseudo']) : '';
if($pseudo!="")
{
$result = $bdd->prepare("SELECT * FROM ajax_tchat_user WHERE pseudo = :login");
$result->execute(array(':login' =>  $pseudo));

if ($row = $result->fetch())
{
if($row["ip"] == $_SERVER["REMOTE_ADDR"] && time()-$row["date"]<60 )
{
$ActuPseudoID = $row["id"];
}
else if (time()-$row["date"]>60)
{
$ActuPseudoID =  $row["id"];
}
else
{
$erreur = "Ce pseudo est déjà en cours d'utilisation";
}
}
else
{
$result->closeCursor();
$erreur = "Pseudo non autorisé";
}

if(!isset($erreur))
{
$_SESSION["pseudo"] = $pseudo;
$_SESSION["ActuPseudoID"] = $ActuPseudoID;
$bdd=NULL;
echo '<meta http-equiv="refresh" content="0;URL=ajax_tchat_page.php">';
exit;
}
}

$bdd=NULL;
?>
<div id='conteneur'>
<h1>Mon tchat</h1>
<?php if(isset($erreur)){ echo "<p>".$erreur."</p>"; }?>
<form action='ajax.php' method='post'>
Votre Pseudo : <input class='le213'  type='text' name='pseudo' autocomplete='off' />
<input type='submit' value='tchatter' />
</form>
</div>
</body>
</html>

V-C - La partie chat

Analysons la page ajax_tchat_page.php.

Pour commencer, nous activons les sessions. En effet, nous avons besoin de récupérer le pseudo dans nos fichiers PHP. Ensuite nous contrôlons que le visiteur de cette page est bien logué, sinon, retour à l'index !

Pour bien gérer tous les modules utilisés dans ce chat, nous avons choisi UTF-8. Il faut le préciser à nos codes PHP et HTML (voir le DOCTYPE du fichier ajax_sql.php). Et enfin, il faut que les tables MySQL soient homogènes !

En ce qui concerne :

$moiChri="O";
require("ajax_sql.php");

Il s'agit d'une méthode conseillée pour sur protéger le fichier de connexion SQL ajax_sql.php. En effet, au début de ce fichier il y a :

if (!isset($moiChri))   {
header('Location: index.php');
exit;
}

Ainsi, un appel direct en HTTP de ajax_sql.php éjecte de suite le curieux !

Le « O » donné en valeur à $moiChri signifie que le DOCTYPE sera affiché, mais ça vous l'aviez vu juste en lisant le code PHP. ;-)

Voilà, tout est prêt et nous retrouvons notre code AJAX tel que nous l'avions étudié précédemment. Mais avec quelles différences ? Simplement nous allons demander au fichier PHP du serveur de répondre à nos souhaits.

1) Chaque pseudo aura un avatar. C'est le code PHP du site qui va nous renvoyer cet avatar. Nous verrons cela plus tard.

2) La discussion sera réaffichée régulièrement. Nous allons appeler notre code ajax_tchat_pdo.php sur le serveur grâce à cette première ligne :

var timer = setInterval(Affiche_Tchat,5000);
// le timer va donc appeler toutes les 5 secondes Affiche_Tchat() qui est plus bas dans le code
function Affiche_Tchat(){
<?PHP
echo "pseudo='".$pseudo."';";
?>
maFonctionAjax("", pseudo,"Affiche_Tchat");
}

Cela constitue la requête AJAX. Le fichier PHP va faire son boulot et renvoyer un echo contenant tout le chat. Voici le code qui gère le retour de la requête :

MonAjax.onreadystatechange = function()
{
if (MonAjax.readyState == 4 && MonAjax.status == 200)
{
if(action=="Affiche_Tchat") { document.getElementById('LeRetourL').innerHTML = MonAjax.responseText;}
if(action=="Qui_En_Ligne") { document.getElementById('LeRetour').innerHTML = MonAjax.responseText;}
if(action=="Ajout") { document.LeForm.message.value='';}
setTimeout("image()", 2000);
}
}

Nous reviendrons sur la dernière instruction (setTimeout("image()", 2000);) qui retire le GIF animé d'attente lorsque l'action est terminée. Puisque nous sommes dans le cas où action=="Affiche_Tchat", il va exécuter :

if(action=="Affiche_Tchat")
{
document.getElementById('LeRetourL').innerHTML = MonAjax.responseText;
}

C'est-à-dire afficher tout le chat en plaçant le texte de réponse dans la div ayant pour id LeRetourL.

3) La liste des pseudos en ligne sera affichée. C'est exactement le même mécanisme qui va nous servir. Reprenons le début du JavaScript :

var ctimer = setInterval(Qui_En_Ligne,10000);

Cette instruction va appeler toutes les 10 secondes la fonction Qui_En_Ligne(). Le résultat sera alors affiché ainsi :

if(action=="Qui_En_Ligne")
{
document.getElementById('LeRetour').innerHTML = + MonAjax.responseText;
}

4) Une zone de saisie est bien sûr prête pour participer au chat. Ici plus besoin de timer. C'est le visiteur qui, s'il valide un nouveau message, va appeler directement la fonction AJAX et donc le message sera enregistré dans MySQL comme nous allons le voir par après.

5) Un GIF animé d'attente nous indiquera toute action en cours non terminée. Enfin notre mystérieux GIF d'attente action en cours est complètement enfantin. Souvenez-vous, dans le HTML ce GIF est bien présent mais 'hidden'.

<img src='ajax/ajaxloader.gif' style='visibility:hidden' id='load' />

Intervient également la notion de requête synchrone ou asynchrone (false pour synchrone et true pour asynchrone dans le open). Une requête synchrone va bloquer l'exécution de la suite des instructions JavaScript tant que la requête n'est pas terminée. Une requête asynchrone ne va pas être bloquante. Pendant que la requête s'exécute, le reste du code JavaScript s'exécute également. Cela permet de ne pas devoir patienter en cas de requêtes qui prendraient beaucoup de temps.

MonAjax.onreadystatechange = function()
{
if (MonAjax.readyState == 4 && MonAjax.status == 200)
{
if (document.getElementById)
{
if(action=="Affiche_Tchat") { document.getElementById('LeRetourL').innerHTML = MonAjax.responseText;}
if(action=="Qui_En_Ligne") { document.getElementById('LeRetour').innerHTML = MonAjax.responseText;}
if(action=="Ajout") { document.LeForm.message.value='';}
setTimeout("image()", 2000);
}
}
else
{
document.getElementById('load').style.visibility="visible";
}
}

//===== et plus bas

function image()
{
document.getElementById('LeRetourL').style.visibility="visible";
document.getElementById('load').style.visibility="hidden";
}

À chaque action lancée, nous attendons une réponse via un écouteur d'événements : MonAjax.onreadystatechange = function(){}. Et tant que nous ne recevons pas de réponse, c'est document.getElementById('load').style.visibility="visible"; qui laisse l'image visible ! Par contre, dès que la réponse donne les status 4 et 200, alors on appelle setTimeout("image()", 2000); qui rend le GIF animé invisible.

<?php
session_start();
$pseudo = (isset($_SESSION['pseudo'])) ? $_SESSION['pseudo'] : '';
if($pseudo=="") header("location:index.php");

header('Content-type: text/html; charset=UTF-8'); // indication encodage pour PHP
$moiChri="O";
require("ajax_sql.php");
?>
<script type="text/javascript">
var timer = setInterval(Affiche_Tchat,5000);
var ctimer = setInterval(Qui_En_Ligne,10000);
function maFonctionAjax(message, pseudo,action)
{
var MonAjax;
if (window.XMLHttpRequest){ MonAjax = new XMLHttpRequest();}
else if (window.ActiveXObject) {MonAjax = new ActiveXObject('Microsoft.XMLHTTP');}
else {
alert("Votre navigateur n'est pas adapté pour faire des requêtes AJAX...");
MonAjax = false;
}

MonAjax.open('POST',"ajax_tchat_pdo.php",true);
MonAjax.onreadystatechange = function()
{
if (MonAjax.readyState == 4 && MonAjax.status == 200)
{
if (document.getElementById)
{
if(action=="Affiche_Tchat") { document.getElementById('LeRetourL').innerHTML = MonAjax.responseText;}
if(action=="Qui_En_Ligne") { document.getElementById('LeRetour').innerHTML = MonAjax.responseText;}
if(action=="Ajout") { document.LeForm.message.value='';}
setTimeout("image()", 2000);
}
}
else
{
document.getElementById('load').style.visibility="visible";
}
}

MonAjax.setRequestHeader('Content-type','application/x-www-form-urlencoded');
MonAjax.send('message='+message+'&pseudo='+pseudo+'&action='+action);
}

function Affiche_Tchat(){
<?PHP
echo "pseudo='".$pseudo."';";
?>
maFonctionAjax("", pseudo,"Affiche_Tchat");
}

function Qui_En_Ligne(){
<?PHP
echo "pseudo='".$pseudo."';";
?>
maFonctionAjax("", pseudo,"Qui_En_Ligne");
}

function image()
{
document.getElementById('LeRetourL').style.visibility="visible";
document.getElementById('load').style.visibility="hidden";
}
</script>

<div class='centre01'>
<h1>Mon tchat, connectez en tant que <?php echo $pseudo; ?></h1>
<br />
<form id='LeForm' name='LeForm'  method='post' onsubmit="maFonctionAjax(this.message.value,this.pseudo.value,'Ajout');return false" action='' >
Message    <input  class='le413' name='message' id='message' type=text  autocomplete='off'  ><br />
<?PHP
echo "<input name='pseudo' id='pseudo' type='hidden' value='".$pseudo."' >";
?>
<input type=submit value='envoyer'  /><br />

</form>

<div id='LeRetour' class='LeRetour' style='visibility:visible'>
</div>
<img src='ajax/ajaxloader.gif' style='visibility:hidden' id='load'  name='load' />
<br />
<div id='LeRetourL' class='LeRetourL' style='visibility:visible'>
</div>
</div>
</body>
</html>

V-D - Le serveur

Analysons la page ajax_tchat_pdo.php appelée sur le serveur.

Ce code n'est qu'un des moyens utilisables par notre AJAX afin d'obtenir une réponse à ses requêtes. Ainsi ce code PHP ne fait que renvoyer du texte vers celui qui l'appelle sous forme d'echo ! Il est très important à ce niveau d'en noter le comportement.

- Tout echo sera reçu par le module AJAX.

- Attention de bien concatener vos résultats (réponses) si vous avez plusieurs echo, car leur ensemble formera une et une seule réponse !

- Une requête AJAX n'est pas obligée d'envoyer une réponse. Cependant, bien des codes AJAX plantent à cause du manque de réponse, car le code de retour gère peut-être systématiquement une réponse. Dans ce cas, vous pouvez faire un echo "";, ce qui vous facilitera la gestion des réponses vides.

- Surtout, compte tenu de ceci, vous devez masquer tout message d'erreur ! Ou bien l'analyser dans le retour de la requête AJAX lorsque vous recevez le résultat.

Alors, voyons le code serveur. Il est vraiment presque inutile de vous le décrire. ;-) En effet, nous avions 3 requêtes dans notre code AJAX, or nous voyons de suite les 3 if du PHP. Voici tout de même quelques mots d'explications.

L'instruction principale est un echo de réponse dont nous avons déjà parlé. Il est en dernier dans le PHP et se trouve après toute fermeture des « } ». Ainsi, nous sommes certains qu'AJAX recevra une réponse même vide.

Par ailleurs, vous trouverez vous-même la gestion de qui est en ligne, car dès qu'un pseudo reposte, donc en action Ajout, son compteur de temps est remis à neuf par :

$result = $bdd->prepare("UPDATE ajax_tchat_user SET date = :Lenow WHERE id = :Avat");
$result->execute(array(':Lenow' => $now,':Avat' => $ActuPseudoID ));

Mais vous retrouvez le même code dans qui est en ligne ! ;-( Bien sûr, car si je vais boire un café, mais que ma page est ouverte, je suis bien toujours loguée et mon pseudo ne peut être pris par quelqu'un d'autre. Voilà, le reste de cette page est un banal mélange de PHP et MySQL. ;-)

<?PHP
session_start();
$moiChri="N";
require("ajax_sql.php");
header('Content-type: text/html; charset=UTF-8');
$pseudo = (isset($_SESSION['pseudo'])) ? secur($_SESSION['pseudo']) : '';
$ActuPseudoID = (isset($_SESSION['ActuPseudoID'])) ? $_SESSION['ActuPseudoID'] : '';
$action = (isset($_POST['action'])) ? secur($_POST['action']) : '';
$message = (isset($_POST['message'])) ? secur($_POST['message']) : '';
$liste="";
if($pseudo=="" || $action=="" )
{
$liste="Vous devez être connecté pour utiliser le tchat";
}
else
{
if($action=="Qui_En_Ligne") //=======si appel AJAX "Qui_En_Ligne" =======
{
$now = time();
$liste= "Connectés : ";
$result = $bdd->prepare("SELECT * FROM ajax_tchat_user WHERE :Lenow -date <60 ");
$result->execute(array(':Lenow' => $now));

while ($row = $result->fetch())
{
$liste .= $row['pseudo'].", ";
}

$liste  = substr($liste,0,-2);
$result->closeCursor();
$result = $bdd->prepare("UPDATE ajax_tchat_user SET date = :Lenow WHERE id = :Avat");
$result->execute(array(':Lenow' => $now,':Avat' => $ActuPseudoID ));
}

if($action=="Ajout") //=======si appel AJAX "Ajout" par un visiteur d'un nouveau message ====
{
$message=secur($message);
$result = $bdd->prepare("INSERT INTO  ajax_tchat_messages
(  pseudo ,pseudoid, message , date ) VALUES (:Xpseudo,:Xpseudoid, :Xmessage, ".time().")");
$result->execute(array(':Xpseudo' => $pseudo,':Xpseudoid' => $ActuPseudoID,':Xmessage' => $message));
$result->closeCursor();
$now = time();
$result = $bdd->prepare("UPDATE ajax_tchat_user SET date = :Lenow WHERE id = :Avat");
$result->execute(array(':Lenow' => $now,':Avat' => $ActuPseudoID ));
}

if($action=="Affiche_Tchat") //=======si appel AJAX "Affiche_Tchat" =======
{
$lastid = 0;
$result = $bdd->prepare("SELECT * FROM ajax_tchat_messages WHERE id> :LaLid ORDER BY date DESC ");
$result->execute(array(':LaLid' => $lastid));
$liste .= "<table><tr><td class='tchat1'>Pseudo</td><td class='tchat2'>Edite le</td><td class='tchat3'>message</td></tr>";

while ($row = $result->fetch())
{
$lim=10000+$row['pseudoid'];
// =======l'image (avatar) est ajax/tchat10003.jpg si l'ID du pseudo est 3 assez simpliste, mais vous ferez mieux ===
$LaDate=date("d/m/Y H:i:s",$row['date']);
$liste .="<tr><td><b>".$row['pseudo']."</b></td><td>(".$LaDate.")</td><td><img vspace=8 src='ajax/tchat".$lim.".jpg' align=left alt='' width='31px' />&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;".$row['message']."</td></tr>";
}

$liste .= "</table>";
$result->closeCursor();
$now = time();
$result = $bdd->prepare("UPDATE ajax_tchat_user SET date = :Lenow WHERE id = :Avat");
$result->execute(array(':Lenow' => $now,':Avat' => $ActuPseudoID ));
}
}
echo $liste;
?>

VI - Sources

Vous pouvez télécharger les sources :
source pour la racine du site de test
repertoire ajax des images et objets

VII - Remerciements

Je remercie Zoom61 pour sa relecture attentive, un travail toujours fastidieux. Et puis je remercie ceux qui m'ont aidé pour ce premier article, comme Sara Galloy qui est à l'origine de cette "première aventure". Ou bien FirePrawn qui m'a apporté de l'aide. Mais c'est une mention spéciale qui va à vermine sans qui cet article n'aurait pu aboutir. Je remercie également notre sympathique et notre ami Bovino, infatigable technicien qui a veillé à l'intégrité de mon code !