[PHP] moteur de recherche interne, requête insensible aux accents

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : [PHP] moteur de recherche interne, requête insensible aux accents

par leica69 » 08 avr. 2009, 23:28

Merci pour ces considérations. J'en tiendrai compte pour faire évoluer mon "système de recherche".

Antonio

par Berzemus » 08 avr. 2009, 22:50

Un moteur de recherche hein ? Voyez-vous ça... Je suis bien désolé de le dire, mais c'est autant un moteur de recherche que google une outil boursier.

Alors oui, google permet d'obtenir et de suivre le cours de la bourse, mais il y a, comment dire, des outils plus adaptés.

Pour commencer, il ne faut pas "faire" un moteur de recherche. D'abord parce que "like" n'a rien d'une fonctionnalité de recherche (c'est simplement une expression de comparaison. Il n'y a pas de classement des résultat, de calcul complexe propre à une vraie recherche, ni même de simples opérateurs booléens). Il faut d'abord savoir en utiliser un.

C'est bien dommage d'utiliser LIKE, alors que MySQL offre un magnifique module de recherche en texte intégral. A toi la recherche avec extension de requête, de classification personnalisée, d'opérateurs booléens j'en passe et des meilleures. Bref, quelque chose qui approche de la vraie recherche.

Ensuite, c'est bien rare d'utiliser comme base de la recherche, comme source des données, la même version que celle diffusée, lisible et consultable. D'habitude, on tendrait plus vers une version "normalisée" du texte, que l'ordinateur pourra indexer facilement: on filtre les mots trop courants, on enlève tout les accents, les majuscules, etc.

On fait correspondre ces données aux données originelles par la magie des bases de données relationnelles, on effectue une recherche full-text en utilisant un input filtré et normalisé par php auparavant, et on obtient un résultat quand même plus satisfaisant, qu'on peut vraiment qualifier de recherche, même si on est encore loin de l'avoir fait, le moteur en question.

Ceci dit, ce que j'expose convient à de la recherche en texte intégral. Si on recherche un mot-clef dans une structure du type arborescence, "like" ne fera pas trop de dégâts (même si on met de côté tout ce qui est fuzzy search ou stemming). Mais le côté "normalisé" devrait quand même s'étudier.

par leica69 » 08 avr. 2009, 22:44

Ma requête SQL ne posait pas de problème, insensible à la casse et aux accents.
Mon interclassement est utf_unicode_ci

Par contre, le PHP est sensible aux accents. C'est pour ça que la procédure est un peu plus complexe. Le tout est de mettre en forme le texte de la sélection.

par naholyr » 08 avr. 2009, 20:55

Beaucoup de bidouilles dans la solution que tu as préféré utiliser :?

C'est toi qui vois mais question perf, il n'y aura rien à voir entre les deux méthodes ;)

Dans quelle collate sont déclarées tes tables ? Il y a fort à parier qu'en déclarant le bon encodage pour ta connexion, alors le LIKE sera insensible à la casse et aux accents naturellement sans aucune bidouille sur la chaine de départ.
Cela marche en tous cas avec latin1_swedish_ci de mémoire, mais il faudrait que je revérifie ça fait bien longtemps que je n'ai rien fait d'autre que de l'UTF-8.

par leica69 » 08 avr. 2009, 20:10

Merci.

Je croyais avoir déjà répondu!?!?

Je ne veux justement pas changer ma base en Latin1.

J'ai trouvé une solution en demandant de l'aide dans un autre forum. Voici la solution:
http://forum.webrankinfo.com/moteur-rec ... 09528.html

par naholyr » 08 avr. 2009, 07:56

Ton script est sensible aux SQL-Injections. Protège ta variable avec $recherche = mysql_real_escape($recherche), sinon si quelqu'un cherche '; DROP TABLE table; -- ça va pas te faire plaisir... Sauf si tu travailles avec magic_quotes à On, ce qui te vaudrait un aller simple pour l'Enfer.



Ensuite concernant plus directement ton problème, tout se passe côté MySQL :
- Le type du champ pour l'insensibilité à la casse.
- La collation pour que cette insensibilité à la casse concerne aussi les accents.
- La collation encore pour l'insensibilité aux accents.

Un type VARCHAR non BINARY te permettra d'être insensible à la casse avec l'opérateur LIKE.
Une collation *_unicode_ci te permettra d'être insensible aux accents et à la casse (accents compris).

Ensuite la collation dépendra évidemment de l'encodage de ton client MySQL. Si tu n'en as spécifié aucun il s'agira de "latin1". L'idéal étant d'en spéficier un (quite à ce que ce soit "latin1" mais tant qu'à faire je préfère "utf8" qui lui au moins contient réellement tous les caractères de l'alphabet "unicode"...), et ainsi d'être cohérent entre l'encodage utilisé par ton client et celui utilisé sur ta table.
IMPORTANT : cet encodage devrait être le même sur tous tes champs, évidemment !


Voir mysql_set_charset() pour changer le charset du client MySQL. Si tu n'as pas PHP 5.2.3, tu peux toujours exécuter une requête "SET NAMES latin1" ou "SET NAMES utf8" pour spécifier ce charset juste après ta connexion.



Test :

Code : Tout sélectionner

SET NAMES='utf8'; CREATE DATABASE `test_search` ; CREATE TABLE `test_search`.`search` ( `texte` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL , INDEX ( `texte` ) ) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_unicode_ci INSERT INTO `test_search`.`search` ( `texte` ) VALUES ( 'azerty' ), ( 'AZERTY' ), ( 'azérty' ), ( 'AZÈRTY' ), ( 'AZRTY' ); -- Les requêtes suivantes renvoient le même résultat : azery + AZERTY + azérty + AZÈRTY SELECT * FROM `search` WHERE `texte` LIKE '%é%' SELECT * FROM `search` WHERE `texte` LIKE '%é%' SELECT * FROM `search` WHERE `texte` LIKE '%E%'

[PHP] moteur de recherche interne, requête insensible aux ac

par leica69 » 07 avr. 2009, 22:54

Bonjour,
je suis en train de faire un moteur de recherche interne pour mon site.

1/ Je récupère le mot cle de recherche transmis par formulaire:

Code : Tout sélectionner

$recherche = $_POST['rech']; $recherche = trim($recherche);
2/ je fais une recherche dans ma base de données (PHP5, utf8_unicode_ci)
Je souhaite que les mots recherché soient surlignés dans l'affichage final

Code : Tout sélectionner

$requete="SELECT * FROM table WHERE champ1 LIKE '%$recherche%' OR champ2 LIKE '%$recherche%''"; $resultat=mysql_query($requete) or die ("Problème lors de la requête. Erreur: ".mysql_error()); while($ligne=mysql_fetch_array($resultat)){ $valeur1 = $ligne[champ1]; $valeur2 = $ligne[champ2]; // recherche et remplacement du mot de la recherche pour l'entourer d'un <span> de mise ne forme $pattern = '('. quotemeta($recherche) .')'; $replacement = "<span class='selection'>\\1</span>"; $valeur1 = eregi_replace($pattern, $replacement, $valeur1); $valeur2 = eregi_replace($pattern, $replacement, $valeur2); // Affichage du résultat mis en forme echo "<p>$valeur1 </p>"; echo "<p>$valeur2 </p>"; }
Maintenant, je vous explique mon souci:
Quand je fais la recherche SQL, elle est insensible aux accents.
Quand je fais la recherche PHP, elle est insensible à la casse mais sensible aux accents.

Si je fais une recherche sur "pre":
- SQL va me retourner les enregistrements contenant "précision", "âpre", "premier",...
- PHP va uniquement surligner "âpre", "premier"

Mon problème est une incohérence des recherches. Je vais avoir des champs de texte sans rien de surligné, c'est déroutant pour l'utilisateur (et pour moi).

Je souhaite avoir deux recherches cohérentes:
Soit tout insensible aux accents // Soit tout sensible aux accents

J'ai essayé de remplacer tous les caractères accentués par leur équivalent sans accent. Le pb est que je me retrouve avec un texte de résultat sans les accents. Je veux un texte juste (accentué) en retour.

J'espère que qqn pourra m'aider!!

D'avance, merci,
Antonio