[RESOLU] requête préparée et AGAINST

Eléphanteau du PHP | 18 Messages

11 juil. 2025, 16:23

Le problème que j'ai est le suivant

Comment utiliser une requête préparée avec MATCH et AGAINST?

Le code

Code : Tout sélectionner

$stmt = mysqli_prepare($bdd, "SELECT adresse FROM groupes_index WHERE groupe LIKE ?");
Fait ce que je veux mais avec un seul mot provenant d'un formulaire de recherche et qui remplace le "?" grace à

Code : Tout sélectionner

mysqli_stmt_execute($stmt, [$_GET["Mot"]]);
D'après mon expérience "AGAINST ?" ne fonctionne pas.
Que doit-on écrire pour que

Code : Tout sélectionner

$stmt = mysqli_prepare($bdd, "SELECT adresse FROM groupes_index WHERE MATCH(groupe) AGAINST ?");
fonctionne ?
Merci

Avatar du membre
Mammouth du PHP | 1564 Messages

12 juil. 2025, 14:37

Dans le manuel MySQL (section PREPARE Statement), il est précisé que :
"Parameter markers can be used only where data values should appear, not for SQL keywords, identifiers, and so forth."
https://dev.mysql.com/doc/refman/8.4/en/prepare.html
Autrement dit, les ? ne peuvent être utilisés que pour des valeurs, pas pour des éléments comme MATCH … AGAINST qui font partie de la syntaxe SQL.

Aussi, pour que AGAINST fonctionne, il faut que ta colonne soit indexée avec FULLTEXT.

Si tu veux absolument garder la requête préparée pour les autres parties (genre WHERE id = ? AND MATCH(...)), tu peux mixer :
  1. Préparer la partie MATCH(...) AGAINST ('$mot_escaped')
  2. Utiliser le paramètre ? pour les autres champs
Essaye quand même en formulant correctement ta requête (en ajoutant les parenthèses et les ' : ('?')) :

Code : Tout sélectionner

$stmt = mysqli_prepare($bdd, "SELECT adresse FROM groupes_index WHERE MATCH(groupe) AGAINST ('?')");
https://www.mysqltutorial.org/mysql-ful ... h-against/

Eléphanteau du PHP | 18 Messages

13 juil. 2025, 16:25

j'avoue que je n'ai pas très bien compris ta réponse. Je suis très débutant en sql. J'ai lu que lorsqu'une requête vient de l'extérieur il fallait absolument sous peine de mort faire une requête préparée sinon quelqu'un de mal intentionné peut tout casser. Le problème est que les tutos et autres documents n'en font jamais ! Ils écrivent des codes SELECT ceci cela et c'est tout.
sauf qu'on ne peut pas écrire ça directement puisque select n'est pas du code php...
Je t'avoue n'avoir aucune idéée d'une initiative à prendre.

Lorsque j'ai mis ton code avec AGAINST('?') j'ai reçu ça

ValueError: mysqli_stmt_execute(): Argument #2 ($params) must consist of exactly 0 elements, 1 present in H:\proglyrics\recherche.php on line xxx

pour la ligne

Code : Tout sélectionner

mysqli_stmt_execute($stmt, [$_GET["Mot"]]);
Si je mets simplement AGAINST (?) Je n'ai aucun retour ! Pas d'erreur mais rien.
Alors je ne sais pas si c'est la requête qui plante et ne retourne rien ou si c'est l'affichage avec le code

Code : Tout sélectionner

$result = mysqli_stmt_get_result($stmt); //récupère le jeux de résultat // parcours des lignes du résultat while ($row = mysqli_fetch_array($result)) { echo '<a href="'.$row["adresse"].'"> toto</a><br>' ; }
qui plante.

C'est difficile de ne rien pouvoir vérifier avec des "print"

Eléphanteau du PHP | 18 Messages

13 juil. 2025, 16:41

j'ai oublié de te dire que ma table est "en principe" indexée avec ma colonne FULLTEXT à moins d'un bug sordide !!
je te mettrais bien une copie écran de PhpMyAdmin mais je ne sais pas comment mettre une image. Le "Img" de la barre ne fait rien du tout

Avatar du membre
Mammouth du PHP | 1564 Messages

13 juil. 2025, 19:36

Alors, le mieux sera de débuguer, commence par faire une requête simple, sans la préparer, en mettant ton "mot" directement à la place de ? :

"SELECT machin truc AGAINST ('ton mot')", fait ceci dans ton SGBD (phpmyadmin, dans ton cas) puis regarde s'il affiche des résultats ou des erreurs.

S'il affiche des résultats, on peut ensuite passer à la suite du débuguage.

Ensuite, suite du débuguage, vérifier ce que $_GET["Mot"] contient, s'il existe et n'est pas vide.

PS, on est pas obligé de passer par une requête préparée "sous peine de mort", il suffit de contrôler ce qui entre dans tes requêtes SQL, on dit de ne jamais faire confiance à l'utilisateur, toujours vérifier. Tu peux très bien faire une requête non préparée en échappant correctement les caractères qui permettent une injection SQL.

Eléphanteau du PHP | 18 Messages

17 juil. 2025, 18:15

j'ai eu la même idée avant de t'avoir lu DONC :
le code

Code : Tout sélectionner

$resultat=mysqli_query($bdd,"SELECT adresse FROM groupes_index WHERE groupe LIKE 'airbag' "); while( $row = mysqli_fetch_array($resultat) ) {echo '<a href="'.$row["adresse"].'"> toto</a><br>' ; };
donne ce qu'il faut.
Le code

Code : Tout sélectionner

$resultat=mysqli_query($bdd,"SELECT adresse FROM groupes_index WHERE MATCH(groupe) AGAINST('airbag')"); while ($row = mysqli_fetch_array($resultat)) { echo '<a href="'.$row["adresse"].'">toto</a><br>'; }
ne retourne rien du tout ! il n'y a pas d'erreur non plus.
Et là Grand mytère car je n'ai fait que recopier ce qui se trouve ici
https://zestedesavoir.com/tutoriels/730 ... c-fulltext

A propos ds requêtes préparée j'ai opté pour le bricolage

Code : Tout sélectionner

if (strpbrk($groupe,'(),./\*;')!=false) exit('il y a des caractères non alphanumériques') ;
c'est peut-être pas le rêve mais je me dis que ça doit protéger quand même

Avatar du membre
Mammouth du PHP | 1564 Messages

17 juil. 2025, 18:50

As tu essayé dans ton SGBD ? Je vois que tu colle des requêtes PHP pour une page, as tu essayé dans ton SGBD ?

Ton utilisation de strpbrk fait peur, c'est pas du tout propre pour moi, si tu veux uniquement des caractères alphanumériques, demande lui directement avec une REGEX :

Code : Tout sélectionner

if (!preg_match('/^[a-zA-Z0-9_]+$/', $groupe)) { exit('Caractères non autorisés'); }
Si tu fait des requêtes préparées, comme tu le dit juste au dessus de ton code, tu n'a pas à te soucier d'échapper les caractères. On échappe/vérifie l'entrée utilisateur, seulement si on utilise pas la préparation de requête, soit avec mysqli_query().

Info optimisation de code :
Je le répète, si tu utilise LIKE sans "%" autant utiliser "=" à la place de "LIKE" : WHERE machin = 'truc'
Et utiliser mysqli_fetch_assoc à la place de *_array, car tu n'utilisera jamais le tableau avec leur index, uniquement avec leur noms. La différence de performance est minime, voire négligeable dans des petits volumes de données mais mis bout à bout, ton code sera plus performant.

Eléphanteau du PHP | 18 Messages

20 juil. 2025, 14:15

j'ai fait dans phpmyadmin. Effectivement avec match il n'y a pas de résultat????????
mais je remarque que les "instructions" select from where match sont colorée alors que against ne l'est pas
Le seul truc que j'ai trouvé pour débugger est cocher "profile" mais ça ne m'a pas dit grand chose.

J'ai aussi essayé en précisant in natural language mode mais c'est la même chose le résultat est vide.

C'est vrai qu'une regext c'est mieux mais j'ai eu peur... La syntaxe des regex variant d'un programme à l'autre j'en ai marre de me prendre la tête.

Curieusement

Code : Tout sélectionner

while ($row = mysqli_fetch_assoc($result)) { echo '<a href="'.$row["adresse"].'">toto</a><br>'; }
ne m'affiche rien. Bien sûr comme je travaille en associatif, en théorie, ça devrait, mais dans ma pratique ça ne donne rien là encore je ne sais pas pourquoi

Avatar du membre
Mammouth du PHP | 1564 Messages

20 juil. 2025, 14:41

Faut voir si AGAINST est disponible avec la version de ton MySQL installé, des fois que.... Faire une recherche à partir de quand il devient disponible et faire la comparaison avec ta version installée.
Curieusement

while ($row = mysqli_fetch_assoc($result)) { echo '<a href="'.$row["adresse"].'">toto</a><br>';
}
ne m'affiche rien.
Donne ta requête initiale, ça aide à savoir ce que tu vient de faire pour utiliser fetch assoc.

Eléphanteau du PHP | 18 Messages

20 juil. 2025, 20:07

J'AI TROUVE POUR LE MATCH AGAINST !!!!!

Et c'était sacrément planqué ! J'étais là à me poser des questions tout en jouant avec mon chien et je me suis dit "table indexée" Est-ce qu'on peut faire afficher l'index ? Et là ... l'éclair et l'illumination .... Ma table est un essai pour voir, donc il y a 5 lignes ... dont 3 comportent le mot 'aibag' qui est donc viré de l'index !!!!

Elle est pas belle celle-là ! Je viens en rentrant de promenade de faire le test avec 'un' puisqu'il y avait un 'aibag un' , deux et trois et c'est passé !!!
J'ai rajouté des lignes et j'ai bien eu mes réponses.

Si je n'avais pas eu cette idée je ne sais pas combien de temps j'aurais pu encore chercher.

reste la question du fetch. Je vais voir ça demain

Avatar du membre
Mammouth du PHP | 1564 Messages

20 juil. 2025, 20:56

Parfait, passe en résolu et ouvre un sujet pour ton fetch. :D