Pour partager cette vidéo sur les réseaux sociaux ou sur un site, voici son url :
Sujets que vous pourriez aussi aimer :
Recherches approchantes - Moteur PHP
Dans la précédente
formation Php , nous avons bâti un
moteur de recherche particulièrement rapide et efficace. Il recoupe tous les mots clés tapés par l'internaute afin de trouver les correspondances strictes, dans un champ particulier de la
base de données MySql . Il extrait les enregistrements correspondants et les restitue sur la
page Web après soumission.
Ici, nous souhaitons lui apporter une amélioration intéressante. Tel que nous l'avons développé jusqu'alors, si seul l'un des mots clés tapés n'est pas trouvé, aucun résultat n'est proposé. Dans ce cas précis, nous souhaitons désormais offrir des enregistrements connexes approchants. Ainsi, nous ne laisserons pas l'internaute sans réponse et continuerons de lui proposer des liens pertinents.
Sources et présentation de la problématique
Nous devons commencer par récupérer les travaux sur le
moteur de recherche , là où nous les avions stoppés. Ainsi, nous pourrons lui greffer les perfectionnements précédemment évoqués.
La décompression conduit aux mêmes fichiers que ceux de la formation précédente. La page Web principale, nommée
index.php , est celle du
moteur de recherche à améliorer par le
code Php . Les sous dossiers fournissent les ressources externes. Le
fichier traitement_chaine.php par exemple, situé dans le
sous dossier fonction , offre deux routines permettant de nettoyer les chaînes de texte. Et nous les avions exploitées pour les besoins du
moteur de recherche .
Ce moteur de recherche se connecte à la
table formations d'une
base de données MySql . Cette base se nomme
supports . Si elle n'existe pas dans votre environnement
PhpMyAdmin , vous devez la créer. Puis, vous devez y importer le
fichier formations.sql situé dans le
sous dossier bdd . Il en résultera la création automatique de la
table formations avec tous sesenregistrements.
Comme l'indique la chaîne de liaison initialisée dans le
fichier connexion.php , situé dans le
sous dossier commun , un compte utilisateur attaché à cette base de données, doit être créé.
...
$liaison = mysqli_connect("127.0.0.1", "moteur", "m127T888");
mysqli_select_db($liaison,"supports ");
?>
Il s'agit donc de répliquer le nom d'utilisateur indiqué dans cette chaîne, ainsi que le nom d'hôte local et le mot de passe. Pensez à lui attribuer les privilèges complets pour être certain d'accéder aux ressources par le code.
De plus et comme vous le savez, le projet doit être référencé dans l'interface d'EasyPhp. Un nom doit lui être attribué. Son adresse issue de l'explorateur Windows, doit être renseignée. Dès lors, l'application apparaît dans la liste des sites émulés par EasyPhp.
Les deux serveurs,
Http et
Database , doivent naturellement être démarrés.
Cliquer sur le lien du projet pour accéder à sa page d'accueil,
Nous retrouvons l'interface Web du
moteur Php que nous avons développé lors de la formation précédente. Si vous essayez les mots clés suivants :
Références absolues Excel , vous obtenez l'extraction de toutes les formations correspondantes. Mais si vous ajoutez simplement un petit terme à la suite, comme ceci :
Références absolues Excel Word .
Plus aucun résultat n'est retourné. Seule la syntaxe de la
requête Sql subsiste. Nous devrons d'ailleurs la masquer. Il s'agissait d'un test à titre de vérification.
Nous estimons donc que ce fonctionnement n'est pas optimisé. L'internaute peut s'être trompé dans les termes choisis. En effet, les références absolues concernent uniquement Excel. Ce dernier mot clé a empêché la vérification exclusive qui consiste à les recouper tous.
Nous souhaitons donc lui proposer des résultats approchants susceptibles de corriger sa demande et de l'intéresser. Mais ces extractions proches ne doivent être suggérées que lorsque la première requête sur tous les mots recoupés, échoue.
Requête Sql approximative
La
requête que nous avons montée dans la formation précédente exploite l'
opérateur AND . Cet
opérateur SQL est exclusif. Dès lors qu'un seul mot clé n'est pas trouvé, l'enregistrement est exclu. Nous proposons d'exploiter l'
opérateur OR pour recouper ces mots clés dans la
clause Where de la
requête SQL . Mais avec lui, il suffit que l'un des mots clés soit trouvé pour que l'enregistrement soit intégré. Nous allons donc devoir développer un
code Php vérifiant la pertinence du résultat proposé, selon la proportion des mots clés saisis qui s'y trouvent. Nous limiterons ainsi la liste des extractions pour ne fournir que les propositions les plus proches.
A la racine du dossier de décompression, cliquer droit sur le fichier index.php ,
Dans le menu contextuel, choisir de l'ouvrir dans un éditeur tel que le Notepad ++,
Nous accédons ainsi à la
structure Html et au
code Php du moteur de recherche. Avant de diriger notre attention sur la
requête Sql approximative, nous devons passer en commentaire l'affichage de la requête. Souvenez-vous, les résultats sont restitués dans le
calque d'identifiant colonne_gauche .
Atteindre la ligne 125 pour un éditeur Notepad,
Adapter le code de la section Php comme suit :
...
<div class="colonne" id="colonne_gauche">
Liste des résultats<br /><br />
<?php
if(isset($_POST["mc"]) && $_POST["mc"]!="")
echo $chaine_fiche;//."<br/>".$requete_et;
?>
</div>
...
Nous ponctuons la syntaxe juste après la restitution de la variable $chaine_fiche, par un point-virgule (;). Puis, nous passons en commentaire la concaténation avec la variable de la syntaxe Sql.
Revenir dans le code de la section Php située en entête de la page Html,
C'est par la
variable $requete_et que nous construisons la syntaxe permettant de questionner la
base de données afin de recouper tous les
mots clés de recherche . Nous devons la conserver bien entendu puisqu'elle livre les résultats stricts. Mais, nous devons prévoir une autre requête à déclencher lorsque cette dernière ne retourne aucun enregistrement. Nous proposons de la nommer
$requete_ou .
Sous la déclaration de la variable $requete_et en ligne 14, ajouter la déclaration de la variable $requete_ou , comme suit :
...
$mots_a_exclure = "avec|pour|dans|";
$tableau_exclure = explode("|",$mots_a_exclure);
$requete_et="SELECT * FROM formations ";
$requete_ou = $requete_et;
...
L'affection est la même dans la mesure où il s'agit de la partie initialisant la
requête . Dans les deux cas en effet, il s'agit de récupérer les informations de tous les champs à partir de la
table formations . C'est la
clause Where qui doit être adaptée dans la boucle passant en revue chacun des mots clés.
Précisément, dans cette boucle for , plus bas dans le code, ajouter les affectations de la variable $requete_ou pour réaliser sa construction :
...
$tableau_mots_cles = explode(" ",$les_mots_cles);
for($i=0; $i<sizeof($tableau_mots_cles); $i++)
{
$chaque_mot = rtrim($tableau_mots_cles[$i], "s"); //Supprime le s de fin soit le pluriel
if(strlen($chaque_mot)>3)
{
if($compteur==0)
{
$requete_et .= "WHERE f_motscles LIKE '%".$chaque_mot."%'";
$requete_ou .= "WHERE f_motscles LIKE'%".$chaque_mot."%' ";
}
else
{
$requete_et .= "AND f_motscles LIKE '%".$chaque_mot."%' ";
$requete_ou .= "OR f_motscles LIKE'%".$chaque_mot."%' ";
}
$compteur++;
}
}
$requete_et .= "LIMIT 0,10;";
$compteur=0;
...
S'il s'agit du premier mot clé (if($compteur==0)), nous débutons la construction de la
clause Where , strictement de la même façon. S'il s'agit des mots clés suivants en revanche (else), nous exploitons l'
opérateur OR à la place de l'
opérateur AND . Nous permettons ainsi d'extraire tous les enregistrements pour lesquels au moins un des mots clés a été trouvé.
C'est ensuite par le
code Php que nous devrons filtrer cette liste pour la rendre pertinente. C'est la raison pour laquelle, au sortir de la boucle while, nous ne posons aucune limite sur le nombre d'enregistrements, contrairement à la requête $requete_et ($requete_et .="LIMIT 0,10;"). En effet, si les 10 premiers résultats n'étaient pas suffisamment cohérents, nous n'aurions pas l'occasion d'analyser les suivants.
Parcourir les enregistrements approchants
Suite au code précédent, la
requete $requete_et est exécutée sur la
base de données MySql . Et c'est alors une
boucle while que nous avions conçue, qui se charge de réceptionner les résultats concordants pour les livrer. Nous avions pris soin d'y inclure un compteur de boucle. Et judicieusement, nous avions nommé cette
variable $compteur . Elle n'était pas utile jusqu'alors. Mais elle va désormais prendre tout son sens. Cette variable est incrémentée à chaque passage. De fait, si à l'issue de la boucle elle vaut toujours zéro, nous pouvons en conclure que la requête stricte ($requete_et) est infructueuse. L'un des mots clés au moins n'a trouvé aucune correspondance avec les autres recoupés.
C'est donc seulement dans ce cas, si
$compteur vaut 0, que nous devons procéder à la
recherche approximative afin de présenter des enregistrements connexes.
...
$chaine_fiche.= "</div>";
$compteur++;
}
if($compteur==0)
{
}
}
...
Donc, comme nous l'avons dit, si ce critère est vrai, aucun résultat strict n'ayant été retourné, nous devons exécuter la
requête approximative .
Entre les bornes de cette instruction conditionnelle, ajouter les deux lignes Php suivantes :
...
if($compteur==0)
{
$chaine_fiche = "Aucun résultat strictement équivalent trouvé. Rubriques connexes les plus pertinentes :<br /><br/>";
$retours = mysqli_query($liaison, $requete_ou);
}
...
Souvenez-vous, la
variable $chaine_fiche est destinée à restituer les résultats de l'extraction sur la page Web. Nous l'initialisons donc avec un message d'information en entête. L'objectif est d'alerter l'internaute sur le fait qu'il s'agit de résultats approchants. Puis, grâce à la
fonction Php mysqli_query , nous exécutons la
requête $requete_ou sur la
base de données MySql .
Désormais, comme nous l'avions fait pour la
requête $requete_et , nous devons parcourir l'ensemble des enregistrements résultants. C'est pourquoi, nous proposons de récupérer le code précédent pour l'insérer dans le traitement de la
requête $requete_ou . Bien sûr, il s'agira d'y ajouter quelques adaptations afin de filtrer les enregistrements trop éloignés de la demande.
Copier l'intégralité de la boucle while (CTRL + C) de la requête $requete_et ,
Coller ce code dans l'instruction conditionnelle, à la suite des lignes précédentes :
...
if($compteur==0)
{
$chaine_fiche = "Aucun résultat strictement équivalent trouvé. Rubriques connexes les plus pertinentes :<br /><br />";
$retours = mysqli_query($liaison, $requete_ou);
while($retour = mysqli_fetch_array($retours))
{
$url_fiche="https://www.bonbache.fr/".supprAccents( supprSpeciaux( strtolower($retour["f_titre"])))."-".$retour["f_num"].".html";
$titre_fiche = stripslashes($retour["f_titre"]);
$titre_fiche = supprSpeciaux(strtolower($titre_fiche));
$titre_fiche = str_replace("-"," ",$titre_fiche);
for($i=0; $i<sizeof($tableau_mots_cles); $i++)
{
$chaque_mot = rtrim($tableau_mots_cles[$i], "s"); //Supprime le s de fin soit le pluriel
if(strlen($chaque_mot)>3)
{
$titre_fiche=str_replace($chaque_mot, "<span style='background-color:yellow;'>".$chaque_mot."</span>",$titre_fiche);
}
}
$chaine_fiche.= "<div style='float:left; width:100%; padding-bottom:5px;'>";
$chaine_fiche.= "<a href='".$url_fiche."' target='_self' style='color:#666666;'>".ucfirst(utf8_encode($titre_fiche))."</a>";
$chaine_fiche.= "</div>";
$compteur++;
}
}
...
Extraire les résultats pertinents
A ce stade, le
code Php restitue tous les enregistrements concordants. Et ils sont forcément nombreux car cette boucle parcourt cette fois les résultats de la
requête $requete_ou qui est très peu restrictive. Donc, nous devons agir en amont dans cette boucle, avant la restitution dans la
variable $chaine_fiche pour filtrer les résultats.
Tout d'abord, au début de la boucle while, ajouter l'initialisation de la variable $proportion :
...
while($retour = mysqli_fetch_array($retours))
{
$proportion = 0;
$url_fiche="https://www.bonbache.fr/".supprAccents(...
...
Cette variable est réaffectée à chaque passage dans la boucle, donc à chaque nouvel enregistrement. Nous souhaitons l'utiliser pour connaître la proportion des mots clés cherchés dans le champ correspondant de l'enregistrement retourné. Si nous jugeons cette proportion satisfaisante, nous retournerons le résultat.
Nous devons incrémenter cette variable à chaque fois que l'un des mots clés tapés est effectivement trouvé dans le
champ f_motscles de la
table formations de la
base de données . Pour ce faire, nous devons exploiter la
boucle for passant en revue chacun d'entre eux.
Dans la boucle for , après l'affectation de la variable $chaque_mot, ajouter l'instruction conditionnelle suivante :
...
for($i=0; $i<sizeof($tableau_mots_cles); $i++)
{
$chaque_mot = rtrim($tableau_mots_cles[$i], "s"); //Supprime le s de fin soit le pluriel
if(strpos(supprAccents( supprSpeciaux( strtolower($retour["f_motscles"]))), $chaque_mot)!==false)
$proportion++;
if(strlen($chaque_mot)>3)
{
$titre_fiche=str_replace($chaque_mot, "<span style='background-color:yellow;'>".$chaque_mot."</span>",$titre_fiche);
}
}
...
Une
requête Sql , telle que nous l'avons définie est insensible aux différences dues aux caractères latins notamment. En revanche, il n'en n'est rien concernant le
code Php à la recherche de correspondances. Donc, pour établir une comparaison concluante, nous exploitons les
fonctions externes supprAccents et supprSpeciaux afin de nettoyer le champ, comme nous l'avions fait sur la chaîne des mots clés. C'est alors la
fonction Php strpos , qui permet de savoir si le mot clé en cours est trouvé dans le champ de l'enregistrement. Donc, si son résultat est différent de false, nous cumulons les points dans la variable proportion en l'incrémentant ($proportion++).
A l'issue de la
boucle for , nous devons précisément exploiter cette variable pour calculer la proportion des mots clés trouvés. Si elle est jugée satisfaisante, par exemple supérieure à 60%, nous pourrons ajouter l'enregistrement connexe, dans la
variable $chaine_fiche destinée à restituer les résultats.
Juste après la boucle for , adapter le code Php comme suit :
...
for($i=0; $i<sizeof($tableau_mots_cles); $i++)
{
$chaque_mot = rtrim($tableau_mots_cles[$i], "s"); //Supprime le s de fin soit le pluriel
if(strpos(supprAccents( supprSpeciaux( strtolower($retour["f_motscles"]))), $chaque_mot)!==false)
$proportion++;
if(strlen($chaque_mot)>3)
{
$titre_fiche=str_replace($chaque_mot, "<span style='background-color:yellow;'>".$chaque_mot."</span>",$titre_fiche);
}
}
$proportion = round($proportion/sizeof($tableau_mots_cles), 2);
if($proportion>=0.6)
{
$chaine_fiche.= "<div style='float:left; width:100%; padding-bottom:5px;'>";
$chaine_fiche.= "<a href='".$url_fiche."' target='_self' style='color:#666666;'>".ucfirst(utf8_encode($titre_fiche))."</a>";
$chaine_fiche.= "</div>";
$compteur++;
}
...
Nous divisons le nombre de correspondances trouvées par le nombre de mots clés tapés. Grâce à la
fonction Php round , nous arrondissons ce résultat à deux décimales. Puis, nous le stockons dans la variable d'origine
$proportion . Sur cette valeur, nous réalisons un test ($proportion>=0.6) à valider pour que l'enregistrement en cours soit assemblé aux résultats à restituer dans la
variable $chaine_fiche .
Nous avons presque terminé. Nous devons néanmoins ajouter une limite à l'extraction. Souvenez-vous, la clause Limit de la
requête $requete_et n'existe pas dans la
requête $requete_ou .
Dans l'instruction conditionnelle de la proportion, réaliser les adaptations suivantes :
...
$proportion = round($proportion/sizeof($tableau_mots_cles), 2);
if($proportion>=0.6)
{
$chaine_fiche.= "<div style='float:left; width:100%; padding-bottom:5px;'>";
$chaine_fiche.= "<span style='color:#CC3300'>".$proportion*(100)."%</span> : <a href='".$url_fiche."' target='_self' style='color:#666666;'>".ucfirst(utf8_encode($titre_fiche))."</a>";
$chaine_fiche.= "</div>";
$compteur++;
if($compteur>=10)
break;
}
...
Dans lachaîne concaténée des résultats, en préfixe de chaque lien vers une formation correspondante, nous inscrivons le pourcentage de pertinence, grâce à la
variable $proportion encadrée de balises Html (<span...) pour sa mise en forme. Et puis, après l'incrémentation de la variable de boucle, un test permet de mettre fin au traitement récursif sur les enregistrements (break), lorsque les 10 premiers satisfaisants ont été consolidés.
Il est temps de tester le moteur de recherche avec ces adaptations.
Enregistrer les modifications et basculer sur le navigateur Web,
Si vous tapez par exemple les mots clés de recherche :
Références absolues Excel , vous obtenez toujours la liste de toutes les correspondances strictes, tel que nous avons développé ce moteur de recherche dans la formation précédente. Dans ce cas en effet, tous les mots clés sans exception sont trouvés dans ces résultats d'enregistrements. En revanche, en début de formation, nous avions tapé les mots clés :
Références absolues Excel Word , pour constater que plus aucun résultat n'était retourné. C'est ce mot clé Word incohérent dans la saisie qui faisait échouer la requête, pour si peu de choses donc.
Taper précisément ces mots clés : Références absolues Excel Word et valider,
Cette fois comme vous le constatez, des résultats connexes pertinents sont proposés. Mieux encore donc, le défaut de saisi est corrigé et l'internaute n'est pas laissé sans réponse.
Les mots clés décelés dans le titre de la formation apparaissent toujours en surbrillance. Les rubriques renvoient vers la page de destination grâce à une URL réécrite.
Les proportions sont affichées en préfixe de chaque résultat pour rendre compte de la pertinence. Dans ce cas précis, elles sont toutes équivalentes.
Taper désormais les mots clés de recherche suivants : Mise en page images tableau Word ,
Puis, valider la recherche pour soumettre les éléments au code Php,
Cette fois les proportions diffèrent, comme vous pouvez le constater. Aucune formation ne semble proposer à la fois de la mise en page, des images et des tableaux de Word.
Mais d'autres sont très proches comme le premier résultat à 83% :
Mettre en page un document Word avec des images . De fait, les propositions sont à la fois cohérentes et pertinentes. L'internaute est judicieusement redirigé. Cette amélioration du moteur de recherche, déjà très efficace, était donc nécessaire.
Dans la formation suivante, afin de préserver les ressources, nous verrons comment mettre en place un système de cache. L'objectif est de restituer des résultats récents depuis la base de connaissances, pour éviter de solliciter inutilement le serveur, qui a déjà fort à faire lorsque le trafic est dense.