Bonjour,

Voila je rencontre un petit problème avec mon code.

Ce que je fais

Je lance une recherche en POST et divise la suite de caractères avec foreach(), je lance dans la boucle des fonctions de recherche en BDD. Problème : il affiche tout les résultats pour chaque termes

<?php
            include('bdd.php');

            $q = $_POST['q'];

            $qS = explode(' ', $q);

            foreach($qS as &$search)
            {
                $search = '%'.$search.'%';

                if($search != null)
                {
                  if(strlen($search) > 2)
                  {
                    $reqS = $bdd->prepare('SELECT * FROM search WHERE title LIKE ? OR resume LIKE ? OR pseudo LIKE ? OR nom LIKE ? OR prenom LIKE ? OR author LIKE ?');
                    ....
?>

Ce que je veux

Je voudrais qu'il n'affiche les résultats qu'une seule fois même si le résultats contient plusieurs termes rechercher.

7 réponses


J'ai écourté le code mais globalement faut faire en une seule recherche title LIKE :term1 OR title LIKE :term2....

Et avec un SELECT DISTINCT ...
ça fonctionne pas ?

Par principe, il faut toujours éviter de faire des requetes dans une boucle, d'autant plus lorsque cela dépend de l'entrée d'un visiteur. Si celui-ci te transmet un texte de 5000 mots (en POST ...) tu vas faire 5000 requetes ?

Accessoirement, et au pire si tu es obligé (ce qui ne m'est jamais arrivé je crois), pense à bien mettre ta préparation avant la boucle, et les execute() dans la boucle. Inutile de préparer 50 fois la même requete ;)

Et pour finir, dans ton cas, comme le dit Grafikart, il te faut créer ta requete dans la boucle, et après la boucle, reconstituer ta requete et l'éxecuter (une seule fois). Et attention, pense à bien passer tout en paramètre, il te faut donc créer ta requete d'un côté, et maintenir un tableau avec les données à part (question de sécu)

Et pourquoi pas ne pas faire une petite REGEX en séparant tous les termes par un | ?

Une idée possible c'est d'utiliser une table temporaire et d'y injecter tous les termes

CREATE TEMPORARY TABLE tmp (terme VARCHAR(50));
INSERT INTO tmp VALUES ('%toto%'), ('%titi'%), ('%tata%');   <<< à faire en php dans une boucle
SELECT DISTINCT * FROM search, tmp WHERE title LIKE terme AND ...

A tester

J'ai trouver un système qui fonctionne

    $query = htmlspecialchars($_POST['q']);
    $querys = explode(' ', $query);

    $Dsql = 'SELECT * FROM search WHERE ';
    $Fsql = '';

    foreach($querys as &$search)
    {
      $search = '\'%'.$search.'%\'';

      if($search != '%%')
      {
        $Fsql .= 'title LIKE '.$search.' OR resume LIKE '.$search.' OR pseudo LIKE '.$search.' OR nom LIKE '.$search.' OR prenom LIKE '.$search.' OR author LIKE '.$search.' OR ';
      }
    }

    $Fsql = substr($Fsql, 0, -4);
    $sql = $Dsql;
    $sql .= $Fsql;
    $sql .= 'ORDER BY type DESC';

    $reqS = $bdd->query($sql);
    $rowS = $reqS->rowCount();

C'est déjà mieux, reste maintenant le côté sécuritaire, il serait largement préférable de préparer ta requete + remplir un tableau, et à la fin, executer la requete avec le tableau de paramètres.