1. ⭐⭐⭐ Grosse PROMO en cours sur ma plateforme SEO My Ranking Metrics
    Rejeter la notice

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

Discussion dans 'Administration d'un site Web' créé par leica69, 7 Avril 2009.

  1. leica69
    leica69 Nouveau WRInaute
    Inscrit:
    25 Octobre 2004
    Messages:
    47
    J'aime reçus:
    0
    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:
    $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:
    $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
     
  2. forty
    forty WRInaute passionné
    Inscrit:
    30 Octobre 2008
    Messages:
    1 930
    J'aime reçus:
    0
    tu peux utiliser un code comme celui ci pour transformer ta mot recherché en regex. ca transforme par exemple "Eléphant" en "[eèéêë]l[eèéêë]phant" pour alimenter ton partern
    Code:
    function regexAccents($chaine) {
    	$accent = array('a','à','á','â','ã','ä','å','c','ç','e','è','é','ê','ë','i','ì','í','î','ï','o','ð','ò','ó','ô','õ','ö','u','ù','ú','û','ü','y','ý','ý','ÿ');
    	$inter = array('%01','%02','%03','%04','%05','%06','%07','%08','%09','%10','%11','%12','%13','%14','%15','%16','%17','%18',
    	                    '%19','%20','%21','%22','%23','%24','%25','%26','%27','%28','%29','%30','%31','%32','%33','%34','%35');
    	$regex = array('[aàáâãäå]','[aàáâãäå]','[aàáâãäå]','[aàáâãäå]','[aàáâãäå]','[aàáâãäå]','[aàáâãäå]',
    	                     '[cç]','[cç]',
    	                     '[eèéêë]','[eèéêë]','[eèéêë]','[eèéêë]','[eèéêë]',
    	                     '[iìíîï]','[iìíîï]','[iìíîï]','[iìíîï]','[iìíîï]',
    	                     '[oðòóôõö]','[oðòóôõö]','[oðòóôõö]','[oðòóôõö]','[oðòóôõö]','[oðòóôõö]','[oðòóôõö]',
    	                     '[uùúûü]','[uùúûü]','[uùúûü]','[uùúûü]',
    	                     '[yýýÿ]','[yýýÿ]','[yýýÿ]','[yýýÿ]');
    	$chaine = str_ireplace($accent, $inter, $chaine);
    	$chaine = str_replace($inter, $regex, $chaine);
    	return $chaine;
    }
     
  3. leica69
    leica69 Nouveau WRInaute
    Inscrit:
    25 Octobre 2004
    Messages:
    47
    J'aime reçus:
    0
    Merci pour l'astuce. Théoriquement ça devrait fonctionner. Mais malheureusement ce n'est pas le cas pour moi.
    J'ai fait une requête simplifiée utilisant ton idée, histoire d'identifier le problème.

    ma chaîne de départ
    Code:
    $desc = "poire très stress tresse tréssaillir(SIC)";
    la chaîne à mettre en gras:
    Code:
    $pattern = "(tr[eèé])"; // qui devrait correspondre à tre, trè, tré
    La substitution pour mettre en gras
    Code:
    $replacement = "<b>\\1</b>";
    le remplacement
    Code:
    $test3 = eregi_replace($pattern, $replacement, $desc);
    echo "$test3";
    et j'obtiens
    dans le code source: poire <b>tr�</b>�s s<b>tre</b>ss <b>tre</b>sse <b>tr�</b>�ssaillir(SIC)
    à l'affichage: poire tr��s stress tresse tr��ssaillir(SIC)

    (ce qui est étonnant c'est que le caractère soit doublé. Le gras fonctionne mais n'est pas affiché dans ce dernier exemple)
    les caractères d'erreur sont des losanges avec des ? à l'intérieur.

    Je suis en UTF-8 dans tout le processus et mon navigateur (firefox) est correctement réglé.

    Uni idée de solution??
     
  4. forty
    forty WRInaute passionné
    Inscrit:
    30 Octobre 2008
    Messages:
    1 930
    J'aime reçus:
    0
    c'est sûrement a cause de l'utf-8. comme les lettres accentuées sont sur deux caractères les [] matchent toutes les lettres.
    essaye de remplacer [eèé] par (e|è|é)
     
  5. leica69
    leica69 Nouveau WRInaute
    Inscrit:
    25 Octobre 2004
    Messages:
    47
    J'aime reçus:
    0
    Ca ne fonctionne toujours pas.

    Je joue un peu avec l'encodage/décodage UTF-8 / ISO-8859-1 pour essayer de contourner le problème mais je bloque encore.
    Code:
    $desc = "poire très stress tresse tréssaillir(SIC)";
    $desc = htmlentities($desc,ENT_NOQUOTES, "UTF-8");
    //desc: poire tr&egrave;s stress tresse tr&eacute;ssaillir(SIC)
    
    $pattern = "(tr[è|e|é])";
    $pattern = htmlentities($pattern,ENT_NOQUOTES, "UTF-8");
    //pattern: (tr[&egrave;|e|&eacute;])
    
    $replacement = "<b>\\1</b>";
    
    $test3 = eregi_replace($pattern, $replacement, $desc);
    j'obtiens ça dans le code source de la page

    Code:
    poire <b>tr&</b>egrave;s s<b>tre</b>ss <b>tre</b>sse <b>tr&</b>eacute;ssaillir(SIC)
    Ce qui me surprend c'est que seul le premier "caractère" (&) du caractère accentué soit dans la balise <b>
     
  6. forty
    forty WRInaute passionné
    Inscrit:
    30 Octobre 2008
    Messages:
    1 930
    J'aime reçus:
    0
    tu ne peux pas mettre [&egrave;|e|&eacute;] car les crochets autorisent les caractères & e g r a v c u t et |
    pour indiquer des chaînes il faut mettre entre parenthèse comme indiqué dans le précédent message : (&egrave;|e|&eacute;)
     
  7. leica69
    leica69 Nouveau WRInaute
    Inscrit:
    25 Octobre 2004
    Messages:
    47
    J'aime reçus:
    0
    Je n'avais pas vu les parenthèses!!!!!
    Ca fonctionne! J'ai quand même du jongler avec les UTF-8 et ISO

    Voici le code, si ça peut aider qqn un jour:

    Code:
    function regexAccents($chaine) {
    	$accent = array('a','à','á','â','ã','ä','å','c','ç','e','è','é','ê','ë','i','ì','í','î','ï','o','ð','ò','ó','ô','õ','ö','u','ù','ú','û','ü','y','ý','ý','ÿ');
    	$inter = array('%01','%02','%03','%04','%05','%06','%07','%08','%09','%10','%11','%12','%13','%14','%15','%16','%17','%18','%19','%20','%21','%22','%23','%24','%25','%26','%27','%28','%29','%30','%31','%32','%33','%34','%35');
    	$regex = array('(a|à|á|â|ã|ä|å)','(a|à|á|â|ã|ä|å)','(a|à|á|â|ã|ä|å)','(a|à|á|â|ã|ä|å)','(a|à|á|â|ã|ä|å)','(a|à|á|â|ã|ä|å)','(a|à|á|â|ã|ä|å)',
    '(c|ç)','(c|ç)',
    '(è|e|é|ê|ë)','(è|e|é|ê|ë)','(è|e|é|ê|ë)','(è|e|é|ê|ë)','(è|e|é|ê|ë)',
    '(i|ì|í|î|ï)','(i|ì|í|î|ï)','(i|ì|í|î|ï)','(i|ì|í|î|ï)','(i|ì|í|î|ï)',	'(o|ð|ò|ó|ô|õ|ö)','(o|ð|ò|ó|ô|õ|ö)','(o|ð|ò|ó|ô|õ|ö)','(o|ð|ò|ó|ô|õ|ö)','(o|ð|ò|ó|ô|õ|ö)','(o|ð|ò|ó|ô|õ|ö)','(o|ð|ò|ó|ô|õ|ö)',			'(u|ù|ú|û|ü)','(u|ù|ú|û|ü)','(u|ù|ú|û|ü)','(u|ù|ú|û|ü)',
    '(y|ý|ý|ÿ)','(y|ý|ý|ÿ)','(y|ý|ý|ÿ)','(y|ý|ý|ÿ)');
    	$chaine = str_ireplace($accent, $inter, $chaine);
    	$chaine = str_replace($inter, $regex, $chaine);		
    	return $chaine;
    }
    
    $recherche = $_POST['rech'];
    $recherche = trim($recherche);
    		
    $pattern = '('. $recherche .')';
    $pattern = regexAccents($pattern);
    $pattern = htmlentities($pattern,ENT_NOQUOTES, "ISO-8859-1");
    	
    $replacement = "<span class='selection'>\\1</span>";
    
    if($_POST['rech'] != ""){
    	if (strlen($_POST['rech']) >= 3){
    		echo "<p>Résultat de la recherche pour <strong>$recherche</strong></p>";
    					
    		$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());
    				
    		if (mysql_num_rows($resultat) > 0){
    			echo "\n<h2>Huiles essentielles</h2>\n";
    		}
    						
    		while($ligne=mysql_fetch_array($resultat)){
    			$val1 = $ligne[champ1];
    			$val2 = $ligne[champ2];
    						
    			$val1 = html_entity_decode(eregi_replace($pattern, $replacement, htmlentities($val1,ENT_NOQUOTES, "ISO-8859-1")));
    			$val2 = html_entity_decode(eregi_replace($pattern, $replacement, htmlentities($val2,ENT_NOQUOTES, "ISO-8859-1")));
    						
    			if(preg_match("/".$pattern."/i",$val1 ) > 0 OR preg_match("/".$recherche."/i",$val1 ) > 0){
    				echo "\n$val1 ";
    			}
    
    			if(preg_match("/".$pattern."/i",$val2 ) > 0 OR preg_match("/".$recherche."/i",$val2 ) > 0){
    				echo "\n$val2 ";
    			}
    					
    		} else {
    			echo "\n<p>Votre recherche doit comporter au moins trois caractères</p>\n";
    		}
    				
    	} else {
    		echo "\n<p>Veuillez saisir un mot pour effectuer votre recherche.</p>\n";
    	}
    }
     
  8. blman
    blman WRInaute accro
    Inscrit:
    5 Septembre 2003
    Messages:
    2 740
    J'aime reçus:
    1
    Réponse hors sujet, mais tu gagnerais en performance en faisant ta requête SQL ainsi :

    Code:
    $requete="SELECT * FROM table WHERE CONCAT(champ1," ",champ2) LIKE '%$recherche%'";
    
    Les OR sont vraiment gourmand en ressources. En concaténant tes champs, tu gagne en performance.
     
  9. leica69
    leica69 Nouveau WRInaute
    Inscrit:
    25 Octobre 2004
    Messages:
    47
    J'aime reçus:
    0
    Cooool! Merci

    C'est d'autant plus pertinent que je fais ma recherche sur 5 champs. Ca me permet aussi de faire un seul LIKE.
    Encore Merci
     
  10. leica69
    leica69 Nouveau WRInaute
    Inscrit:
    25 Octobre 2004
    Messages:
    47
    J'aime reçus:
    0
    Je me rends compte d'un souci supplémentaire.

    Une partie du texte de ma base contient du formatage HTML <strong>Nom</strong>, par exemple.
    Comment faire pour que ma recherche ne prenne pas en compte mes balises?

    Pour rappel, j'ai ceci:
    Code:
    $search = '('. $search  .')';
    $search = regexAccents($search); // voir posts précédents, c'est pour être insensible aux accents
    $search = htmlentities($search,ENT_NOQUOTES, "ISO-8859-1");
    
    $valeur = html_entity_decode(eregi_replace($search, $replacement, htmlentities($valeur,ENT_NOQUOTES, "ISO-8859-1")));
    Je dois modifier mon critère de recherche la bonne syntaxe. Pour l'instant, j'en suis là:
    Code:
    $search = '([^<][\S]*)('. $search .')([\S]*[^>])';
    Dans ce cas précis, si je recherche "tron", c'est la catastrophe!!!
     
  11. forty
    forty WRInaute passionné
    Inscrit:
    30 Octobre 2008
    Messages:
    1 930
    J'aime reçus:
    0
    il y a peut-être une piste avec la fonction preg_replace_callback pour extraire tout ce qui n'est pas balise et faire ensuite ton replace mais je ne suis pas spécialiste
     
  12. blman
    blman WRInaute accro
    Inscrit:
    5 Septembre 2003
    Messages:
    2 740
    J'aime reçus:
    1
    Leica69,

    personnellement, j'ajouterais un champs à ma table qui contient une chaine avec tous tes champs déjà concaténés et formaté (sans balise HTML, sans accent, tout en minuscule et sans les mots qui peuvent être des stop words). Tu indexera ton contenu dans ce champ à chaque fois que tu met à jour la ligne concernée dans ta table.

    Tu y gagnera énormément en ressource et en simplicité au niveau de la recherche. Tu pourrais par exemple l'indexer en FULLTEXT pour gagner en pertinence ou plus facilement le charger en mémoire si tu veux faire de la correction orthographique.

    Parce que là, en voyant la manière dont tu fais la recherche et comment tu la traite en sortie, à mon avis, tu es mal parti. Essaye de traiter tes données au maximum en entrée (indexation de tes keywords)

    PS : sinon tu a la fonction strip_tags() en PHP pour retirer les balises HTML : http://fr2.php.net/strip-tags
     
  13. leica69
    leica69 Nouveau WRInaute
    Inscrit:
    25 Octobre 2004
    Messages:
    47
    J'aime reçus:
    0
    Salut,
    Je m'en suis sorti avec strip_tags()

    C'est vrai que pour la suite, si je complexifie le traitement de la base, je devrais passer par une colonne qui regroupera mes entrées.

    En tout cas, merci pour ta solution.
     
Chargement...
Similar Threads - [PHP] moteur recherche Forum Date
[PHP] Détecter le navigateur / bot en fonction du HTTP_USER_AGENT Développement d'un site Web ou d'une appli mobile Samedi à 06:49
[PHP] Détecter le navigateur / bot en fonction du HTTP_USER_AGENT Développement d'un site Web ou d'une appli mobile 12 Janvier 2017
[PHP] Cookie vide dans une fonction, complet juste avant ou après Développement d'un site Web ou d'une appli mobile 25 Novembre 2014
[php] Cookie d'un domaine vers un sous-domaine Développement d'un site Web ou d'une appli mobile 29 Août 2014
[PHP]Cci mails Développement d'un site Web ou d'une appli mobile 18 Août 2014
[PHP] gethostbyname Développement d'un site Web ou d'une appli mobile 15 Février 2014
[PHP] file_get_contents retourne un "Connection timed out" Développement d'un site Web ou d'une appli mobile 14 Février 2014
[PHP] Regex Complexe Développement d'un site Web ou d'une appli mobile 29 Octobre 2013
[PHP] Formulaire dynamique Développement d'un site Web ou d'une appli mobile 2 Mai 2013
[php] error suite à code antiduplication Développement d'un site Web ou d'une appli mobile 5 Février 2013
  1. Ce site utilise des cookies. En continuant à utiliser ce site, vous acceptez l'utilisation des cookies.
    Rejeter la notice