Aller au contenu
Télécharger Firefox 2

Créer un moteur de recherche avec XmlHttpRequest et PHP

AJAX est une technologie qui permet d'apporter une plus grande richesse dans l'interface et l'ergonomie d'un site. Si il est bon de ne pas en abuser au risque de dénaturer le document web, on peut se laisser aller à la tentation d'apporter quelques fonctionnalités intéressantes. Celle que je vous propose ici consiste à intégrer un moteur de recherche à la manière d'un Google Suggest. Sauf qu'ici vous pourrez avoir un code lisible ^^ Je ne vais pas aborder le concept d'AJAX car certains en parlent déjà très bien. Je vous recommande d'ailleur de lire cet article (Anglophobe, s'abstenir).

PS: Ce billet remplace celui qui s'appelle désormais Introduction à XMLHttpRequest et PHP

Principe

Il faut réunir trois principes pour concevoir cet élément d'application. Tout d'abord nous avons besoin de Javascript et de XMLHttpRequest afin de pouvoir communiquer en arrière plan avec le serveur. Nous allons utiliser la classe XHRConnection pour nous faciliter la vie. Ensuite, il est nécessaire d'avoir un service web se chargera de construire le document XML que nous parserons avec l'API DOM. Enfin afin que l'effet visuel soit efficace nous devrons utiliser les CSS.

Le moteur comprendra une zone de résultat (balise ul) qui ne contiendra pas d'élément de liste. C'est cette liste que nous construirons selon le fichier XML généré et renvoyé par le serveur. Selon que la recherche soit prolifique ou non, la zone de résultat sera cachée ou montrée.

Payes ton code

Vous allez voir, c'est en fait très simple à mettre en place. Voici tout d'abord le formulaire :

<form id="formulaire" action="index.php" method="post">
     <fieldset>
     <p>
          <label for="foo">Saisissez les chaines à rechercher dans le champ de formulaire ci-desous :</label>
          <input type="text" name="foo" id="foo" value="" onkeyup="loadData();" />
     </p>
     <ul id="zoneResultats" style="visibility: hidden;"></ul>
     <p>
          Texte à placer pour tester que les réponses s'affichent par dessus... Lorem ipsum ...
     </p>
     </fieldset>
</form>

Voici le code javascript dont vous aurez besoin :

<script type="text/javascript">
// Déclaration de la fonction de Callback
// + ----------------------------------------------------------------------------------
// + afficherResultats
// + Affiche ou non le conteneur en fonction du résultat de la recherche
// + ----------------------------------------------------------------------------------
function afficherResultats(obj) {
     // Construction des noeuds
     var tabResult = obj.responseXML.getElementsByTagName('resultat');
     document.getElementById('zoneResultats').innerHTML = '';
     if (tabResult.length > 0) {
          // On définit la hauteur de la liste en fonction du nombre de rsultats et de la hauteur de ligne
          var hauteur = tabResult.length * 22; 
          with(document.getElementById('zoneResultats').style) {
               visibility = 'visible';
               height = hauteur + 'px';
          };
          for (var i = 0; i < tabResult.length; i++) {
               resultat = tabResult.item(i); 
               var egt = document.createElement('li');
               var lnk = document.createElement('a');
               var texte = document.createTextNode(resultat.getAttribute('titre'));
               lnk.appendChild(texte);
               lnk.setAttribute('href', resultat.getAttribute('url'));
               lnk.setAttribute('title', resultat.getAttribute('titre'));
               egt.appendChild(lnk);
               document.getElementById('zoneResultats').appendChild(egt);
          }
     }
     else {
          document.getElementById('zoneResultats').style.visibility = 'hidden';
     }
}
// Déclaration de la fonction qui lance la recherche
function loadData() {
     // Création de l'objet
     var XHR = new XHRConnection();
     XHR.appendData("foo", document.getElementById('foo').value);
     // On soumet la requête
     // Signification des paramètres:               
     //      + On indique à l'objet qu'il faut appeler le fichier search.php
     //      + On utilise la méthode POST, adaptée l'envoi d'information
     //      + On indique quelle fonction appeler lorsque l'opération a été effectuée
     XHR.sendAndLoad("search.php", "POST", afficherResultats);
}
     </script>

Coté serveur, nous avons ce petit script PHP :

     header("Pragma: no-cache");
     header("Expires: 0");
     header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
     header("Cache-Control: no-cache, must-revalidate");
     header("Content-type: application/xml"); 

     if(!empty($_REQUEST["foo"])) {
          $rqListBillet = "
               SELECT *
               FROM `blog_blabla`
               WHERE `titre` like '" . $_REQUEST["foo"] . "%'
               ORDER BY `date_parution` DESC";
          $rsListBillet = mysql_query($rqListBillet);
          $xml = "<resultats nb=\"" .  mysql_num_rows($rsListBillet) . "\">";
          if (mysql_num_rows($rsListBillet) > 0) {
               while ($billet = mysql_fetch_object($rsListBillet)) {
                    $xml .= "\n<resultat titre=\"" . str_replace('"', "", $billet->titre) . "\" url=\"/blog/" . $billet->url_page . ".html\" />";
               }

          }
     }
     else {
          $xml = "<resultats nb=\"0\">";
     }
     $xml .= "\n</resultats>";
     echo utf8_encode($xml);

Pour la mise en page, veuillez vous référer au fichier suivant: styles.css.

N'oubliez pas de tester le formulaire, ça se passe ici


Commentaires


[#1] Commentaire rédigé le Mercredi 24 Août 2005 à 16:45 par Olivier

A quand GeSHi pour ton blog ?

[#2] Commentaire rédigé le Mercredi 24 Août 2005 à 16:47 par solo

Il était là un temps. Le temps que je me dise que j'allais m'en passer :)

[#3] Commentaire rédigé le Mardi 06 Septembre 2005 à 06:02 par Marc

Très intéressant. Merci pour ce tutoriel.

[#4] Commentaire rédigé le Jeudi 29 Septembre 2005 à 15:58 par Arnaud

Ca fait un moment que je tourne là dessus pour arriver à faire un truc correct, et en fait mon prob est que ma base de données sur la quelle je tape comporte 150000 articles, donc ca fait un peu lourd à afficher

J'essaye donc ta méthode, en te remerciant de la clarté du site et des rédactions qui y sont effectuées.

@+

Arnaud 8-)

[#5] Commentaire rédigé le Dimanche 09 Octobre 2005 à 11:50 par Alle

Salut a tous
voila je suis débutant et je c pas comment utilser les code si je doit tout méttre dans la méme page ou séparer et le nom des page aussi

si qulqun peut me répondre.
merci

[#6] Commentaire rédigé le Lundi 10 Octobre 2005 à 09:40 par Thanh

Bonjour Alle,

je te proposes de formuler ton besoin sur le forum dreamweaver de http://www.media-box.net

A bientôt.

[#7] Commentaire rédigé le Mercredi 02 Novembre 2005 à 16:08 par Arsenik

Bonjour a tous,

Vous n'avez pas peur que cela fasse un peu bcp de requete sur votre server mysql si tu ne passe pas par un cacheSQL ... fait un like <char>% a chaque lettre tapé ca peux vite saturer ton sql, sans compter les scripts malfaisant pour flooder ta base.

[#8] Commentaire rédigé le Lundi 07 Novembre 2005 à 10:38 par nicolas

Salut,

Super pratique, mais j'ai ça ne fonctionne pas si je base ma recherche sur 2 tables (table mot-cles et une autre mot-associes)

Je lance ma recherche sur tot donc j'ai une 1ere requete sur 'toto%' (table mot-cles), je recupere l'id de ce mot-cles et je fais ensuite une autre requete (table mot-associes)(imbrique dans un while de la 1ere requete) sur cette id et c'est sur cette 2ème requette que je fais ton tuto.

ça ne fonctionne pas....
::whistle

Sais-tu pkoi ?? ou est-ce limité que sur une table ??

Merci de ta réponse

[#9] Commentaire rédigé le Lundi 07 Novembre 2005 à 13:17 par Thanh

Salut nicolas,

je te proposes de soumettre ton code sur ce forum:

http://dreamweaver.media-box.net :)

[#10] Commentaire rédigé le Vendredi 03 Mars 2006 à 10:42 par projektowanie stron

:]

[#11] Commentaire rédigé le Jeudi 09 Mars 2006 à 13:53 par Pierre

Un truc m'échappe : à quel moment se connecte-t-on à la base ?
De plus je ne comprends pas bien cette ligne :
"
$xml .= "\n<resultat titre=\"" . str_replace('"', "", $billet->titre) . "\" url=\"/blog/" . $billet->url_page . ".html\" />";
"

[#12] Commentaire rédigé le Vendredi 10 Mars 2006 à 03:21 par Thanh

@Pierre,

il n'est pas fait ici de détails concernant la connexion à la base de données. Mais il faut le faire bien sûr ;-)

[#13] Commentaire rédigé le Vendredi 10 Mars 2006 à 12:02 par Pierre

Merci, en regardant le code de plus près j'ai mieux compris... Par contre je galère pour débugguer le script PHP, pour lequel je ne parviens pas à voir les erreurs.
Au passage : félicitations :D

[#14] Commentaire rédigé le Vendredi 24 Mars 2006 à 17:07 par mc_cut_killer

Excelent :-)

Merci pour ce script et le travail que tu fourni ...

[#15] Commentaire rédigé le Samedi 25 Mars 2006 à 15:10 par Brida

Bonjour,

Comment faire pour afficher la valeur sélectionnée de la liste dans la zone du formulaire avant le script me redirige sur une autre page.

merci de votre aide

[#16] Commentaire rédigé le Jeudi 13 Avril 2006 à 16:36 par touriste

bonjour, ce framework va t'il encore évoluer?
je fais actuellement une étude sur les frameworks ajax existant et la pérennité est un point essentiel aux différents critères de sélections

[#17] Commentaire rédigé le Jeudi 13 Avril 2006 à 18:38 par Thanh

Bonjour,

j'envisage depuis un certain temps d'ajouter quelques méthodes. Ce n'est pas pour tout de suite mais c'est effectivement dans les tuyaux :)

[#18] Commentaire rédigé le Mardi 18 Avril 2006 à 17:49 par papillon

Merci pour le tuyaux :-)

[#19] Commentaire rédigé le Mercredi 26 Avril 2006 à 16:05 par martial

Bonjour merci pour ce script il est vraiment très bien cependant si l'on tape un % dans la zone de recherche on voit que la liste descend tres bas comment faire via la css pour limiter à (par exemple) 20 reponses et qu'il y ai un scroll pour descendre plus bas ??

[#20] Commentaire rédigé le Mercredi 26 Avril 2006 à 19:31 par Thanh

Martial,

tu peux faire un LIMIT 0, 20 du coté de la requête MySQL :)

[#21] Commentaire rédigé le Vendredi 28 Avril 2006 à 13:20 par Arte

Excelent, merci.
http://www.portia.pl

L'ajout de commentaire a été désactivé pour ce billet.

Trackbacks

Pisteurs vers ce billet (trackbacks entrant)


[#1] Trackback effectué par Hello World

Denis Cabasson (www.developper.com) dans son article (tutoriel) du 10 février 2006 (Ajax - une autocomplétion pas à pas) fait une très bonne approche, quoi qu'un peu complexe à mon goût, de la création d'une liste déroulante en AJAX.Le...

Pistés par ce billet (trackbacks sortant)

Il n'y a pas encore de pisteurs effectué par ce billet.


A propos du billet

Avatar de Thanh

Raccourcis

Rechercher un billet

Sous Rubriques

Photo Pif

Photopif