J'ai installé un petit moteur de recherche interne sur mon site, il marche bien, mais le problème c'est que si l'on rentre deux mots dans la recherche, alors les résultats qui s'affiche doivent contenir ces deux mots qui se suivent exactement.. Je suis en PHP 5.4
Voilà un exemple de ce que je voudrais : Recherche = Sac dos Résultat = sac a dos
En gros je voudrais que la recherche de deux mots soit divisé en deux, pour rechercher à la fois les "sac" et les "dos" et afficher les nom de résultats qui contiennent les deux..
Voilà mon code actuel :
Rechercher un mot :
mysql_connect("XXXXXXXXXXXXX.mysql.db", "XXXXXXXXX", "XXXXXXX") or die (mysql_error ()); // Select database mysql_select_db("XXXXXXXXXX") or die(mysql_error()); // SQL query $recherche = isset($_POST['recherche']) ? $_POST['recherche'] : ''; $strSQL = "SELECT * FROM XXXXXXXXX WHERE nom LIKE '%$recherche%' OR description LIKE '%$recherche%' ORDER BY nom limit 100"; // Execute the query (the recordset $rs contains the result) $rs = mysql_query($strSQL); // Loop the recordset $rs while($row = mysql_fetch_array($rs)) { // Name of the person $strName1 = $row['nom']; $strName2 = $row['prix']; $strImg = $row['img']; // Create a link to person.php with the id-value in the URL $strLink = " $strLink2 = " $strLink3 = " // List link echo "
" . $strLink . "
" . $strLink2 . "
" . $strLink3 . "
"; } // Close the database connection mysql_close(); ?>
Techniquement, vous avec 2 solutions qui me viennent à l'esprit - simplement scinder les mots de recherches (genre un explode sur espace, +, tiret, virgule… enfin tout ce que peut entrer un visiteur…) et construire votre requête, avec un Like sur chaque mot. (une petite boucle sur votre tableau obtenu via explode)
- un peu moins simple de prime abord, mais bien plus simple à gérer. Ue recherche avec une requête à base de MATCH … AGAINST, qui va vous sortir les résultats en fonction de la pertinence (plus il y a de mots, plus le résultat sera en haut de liste). Il faut que les champs recherchés soit en Full Index dans la table.
Je pense que la solution 2 est de loin la plus pertinente.
Et comme mis par Fritz2cat, attention là, votre base de données est à la merci de tous les pirates amateurs. Vous devez impérativement traiter et contrôler ce que le client peut entrer.
Contrôler les données utilisateurs : - quelle que soit la version PHP utilisée, vous devez contrôler ce que l'utilisateur peut entrer. Car n'importe quel pirate amateur ou robot va tester et envoyer du texte, qui lui permettra d'accéder à votre base de données, si vous ne faites rien.
Full Index : c'est une option à mettre sur les champs de votre table, où seront faites les recherches. C'est un index plus poussé qu'un simple index. Mais ça n'est pas supporté par tous les types de champs.
Si on n'utilise pas de moteur de recherche ou de bouton formulaire, c'est plus sécurisé ? Comment contrôler les données utilisateurs ? Je voudrais faire une recherche a base de MATCH j'avais essayé mais cela n'avait pas donné de résultat, je vais retenter.
Pourriez vous me donner le code qui va scinder $recherche en $recherche1 et $recherche2 en pas d'espace? Si possible le placer dans mon code. Merci d'avance, car j'ai cherché mais je ne trouve pas.
Vous avez actuellement ça : $recherche = isset($_POST['recherche']) ? $_POST['recherche'] : ''; $strSQL = "SELECT * FROM XXXXXXXXX WHERE nom LIKE '%$recherche%' OR description LIKE '%$recherche%' ORDER BY nom limit 100";
Je reprends ça : ` $recherche = isset($_POST['recherche']) ? $_POST['recherche'] : '';` Maintenant, je vais faire un explode sur les espace ` $rrr = explode(' ', $recherche);` Ensuite, je construis la requête : $where1 = ''; $where2 = ''; foreach ($rrr as $r) { $where1 .= ($where1 == '' ? '' : ' OR ').' nom LIKE "%$r%"; $where2 .= ($where2 == '' ? '' : ' OR ').' description LIKE "%$r%"; }
Et la requête qui devient : `$strSQL = "SELECT * FROM XXXXXXXXX WHERE $where1 OR $where2 ORDER BY nom limit 100";`
A vérifier, car il faudrait au moins : - vérifier que $r n'est pas vide - vérifier que $r n'est pas une injection de code - supprimer les caractères bizarre qui n'ont rien à faire là…
Avec match against, ça donnerait un truc de ce genre :
SELECT nom, prix, img, MATCH(nom,description) AGAINST (:lesmots IN BOOLEAN MODE) as Relevance FROM `votretable` WHERE MATCH(nom,description) AGAINST(:lesmots IN BOOLEAN MODE) HAVING Relevance > 0.2 ORDER BY Relevance DESC
Merci beaucoup pour votre aide Pppplus, je suis en train d'essayer tout ca. La solution avec Match et Against est elle plus sécure que Like ? Ou il va falloir également contrôler les données utilisateurs ?
Est ce que quelqu'un sait comment activer l'option Full Index chez ovh ? J'ai trouvé Fulltext, je ne sais pas si c'est la même chose et de toute façon j'ai un message d'erreur.. Peut-être que chez OVH cela ne s'appelle pas Full Index, car j'ai bien regardé
$where1 .= ($where1 == '' ? '' : ' OR ').' nom LIKE "%$r%"; $where2 .= ($where2 == '' ? '' : ' OR ').' description LIKE "%$r%";
Activez les erreurs pour voir quelles lignes déconnent. J'ai oublié de fermer le texte : $where1 .= ($where1 == '' ? '' : ' OR ').' nom LIKE "%$r%"'; $where2 .= ($where2 == '' ? '' : ' OR ').' description LIKE "%$r%"';
Si vous activez les erreurs PHP, vous pourrez voir à quelle ligne ça bloque. Il y a peut-être d'autres erreurs, je n'ai pas testé. Et j'ai écrit directement dans la fenêtre du forum, ce qui n'est pas optimum du tout.
Les 2 méthodes ne sont pas plus sécurisées l'une que l'autre.<br /><br />il faut regarder du côté de : mysql_real_escape_string et/ou filter_var<br />si vous passez sur mysqli (obligatoire à partir de php 7), ce sera mysqli_real_escape_string<br /><br />Et sinon full text est bien ce qu'il faut prendre pour les requêtes match against<br /><br />Et un petit tuto assez sympa là dessus : https://blog.axe-net.fr/recherche-pertinence-mysql-fulltext/<br />Je n'ai pas tout lu, mais ça a l'air plutôt clair.<br />Et même le suivant est encore mieux : https://blog.axe-net.fr/tuto-mysql-fulltext-in-boolean-mode/<br />(boolean, c'est ce que j'utilise dans mon exemple plus haut et qui marche très bien)
Merci à Pppplus et Gaston_Phone pour votre aide, Malheureusement, cela ne marche toujours pas, les deux solutions. Avec Val de Gaston ou Where de Pppplus. Par contre grâce aux erreurs j'en sais un peu plus :
"Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead"
Donc si je comprend bien, les lignes de code que vous m'avez donné en plus, ne sont pas compatible Php 5.6.
La seule solution serait de passer au PHP 7 ? De toute façon tôt au tard je m'y serais attelé.