Autocomplete php avec 36000 résultats possible

Discussion dans 'Développement d'un site Web ou d'une appli mobile' créé par sff, 24 Mars 2019.

  1. sff
    sff WRInaute impliqué
    Inscrit:
    2 Février 2005
    Messages:
    525
    J'aime reçus:
    0
    Bonjour,

    j'ai un petit problème et je ne connais pas la meilleure solution à adopter.

    Je souhaite créer un autocomplète (php/mysql/javascript). J'ai crée un code qui fonctionne parfaitement, mais dans celui ci je n'ai que 6 résultats possible. Comment faire pour passer de 6 à 36 000 résultats possible. De plus les 36 000 résultats se trouve dans une bdd.

    Voici le code qui fonctionne :

    PHP:
    $query $_GET['query'];
     
    $values = ['Mickael',
                
    'Julie',
                
    'Francis',
                
    'Jonathan',
                
    'Stephen',
                
    'Alonso'];
     
    if (
    $query) {
        foreach (
    $values as $key => $value) {
            if (
    stripos($value$query) === false) {
                unset(
    $values[$key]);
            }
        }
    }
     
    echo 
    json_encode(array_values($values));
    Voila le code que je souhaite mettre en place : Est ce la meilleure solution ?

    PHP:
    // Récupérer les 36 000 communes
     
    $sql "SELECT name, zipcode, server FROM cities";
     
    $requete $bdd -> prepare($sql);
    $requete->execute();
     
     
    // ICI JE NE SAIS PAS COMMENT FAIRE
     
     
     
    if ($query) {
        foreach (
    $values as $key => $value) {
            if (
    stripos($value$query) === false) {
                unset(
    $values[$key]);
            }
        }
    }
     
    echo 
    json_encode(array_values($values));
    Merci d'avance
     
  2. rick38
    rick38 WRInaute passionné
    Inscrit:
    23 Février 2013
    Messages:
    1 146
    J'aime reçus:
    125
    Eh bien, ton résultat, tu le crées simplement avec les résultats d'une requête qui a un LIKE pour faire la recherche du genre :
    PHP:
    $sql "SELECT name, zipcode, server FROM cities WHERE name LIKE '%" addslashes($query) . "%'";
    C'est la BD qui va faire la recherche, pas le PHP, évidemment plus efficace que de sortir d'abord les 36000 résultats pour que PHP les traite.
     
    #2 rick38, 24 Mars 2019
    Dernière édition: 24 Mars 2019
  3. UsagiYojimbo
    UsagiYojimbo WRInaute accro
    Inscrit:
    23 Novembre 2005
    Messages:
    11 874
    J'aime reçus:
    71
    Et tu peux faire en sorte que l'autocomplete ne se declenche pas à moins de X caractères saisis.
     
  4. spout
    spout WRInaute accro
    Inscrit:
    14 Mai 2003
    Messages:
    8 779
    J'aime reçus:
    237
    Attention qu'un LIKE qui commence par % n'utilise pas l'index.
    Et que ce n'est pas avec addslashes() qu'on escape les paramètres d'une requête (faille d'injection SQL).
     
  5. rick38
    rick38 WRInaute passionné
    Inscrit:
    23 Février 2013
    Messages:
    1 146
    J'aime reçus:
    125
    Si c'est une ville qu'on cherche, c'est vrai que de toute façon inutile de commencer avec un % puisque le début est sûr.
     
  6. rick38
    rick38 WRInaute passionné
    Inscrit:
    23 Février 2013
    Messages:
    1 146
    J'aime reçus:
    125
    Je crois qu'avec un champ UTF8 (je ne mets que de l'utf8 partout) il n'y a pas de faille.
    Mais bon, faut mieux des requêtes préparées paramétrées c'est sûr.
     
  7. colonies
    colonies WRInaute occasionnel
    Inscrit:
    10 Septembre 2006
    Messages:
    473
    J'aime reçus:
    48
    Comme il a été dit plus haut, un bon autocomplete doit faire la recherche au niveau de la base de données.
    Mais un bon auto-complete ne fait pas de recherche sur un champ de la base de données qui n'est pas préparé pour ça, c'est beaucoup trop naïf et lent.
    Par exemple ton champ Cities comporte :
    Manneville-ès-Plains
    Avec un simple like, si l'utilisateur recherche sans tiret ni accents, le Like ne trouvera rien (à moins, pour les accents, d'utiliser une champ avec un interclassement insensible à la casse, ce qui se paye au niveau des perfs).

    Une technique simple à mettre en place, qui offre de bonnes perfs pour le genre de cas évoqué, et qui renvoie de bons résultats :
    - créer un champ supplémentaire insensible à la casse (utf8_bin), avec un index, qui contient le nom de la ville "préparé" : tout en minuscules, pas d'accents, pas d'espaces, pas de tirets, pas d'apostrophes : que des lettres sans accents et des chiffres (car il peut y en avoir si ta liste des villes contient les arrondissements de Paris, Lyon, Marseille). Pour l'exemple de Manneville-ès-Plains, ça donne donc mannevilleesplains
    - quand une recherche arrive, faire subir le même traitement aux termes recherchés.
    - matcher les deux avec BINARY LIKE, et un % uniquement à la fin, sinon, comme l'a indiqué Spout, l'index n'est pas utilisé
    - ne pas oublier de mettre un header expires dans le résultat pour mettre dans le cache du navigateur les résultats. Peut éviter de nombreuses requêtes, si l'utilisateur refait la même recherche, ou efface sa recherche caractère par caractère avec backspace.

    Bonus :
    - coté javascript, au minimum, envoyer le paramètre de recherche en minuscules, pour qu'une recherche sur PARIS appelle la même URL que Paris ou que paris, et donc améliorer l'utilisation du cache si l'utilisateur refait les mêmes recherches avec une casse différente.
    - dans le code d'appel, vérifier si ça sert à quelque chose de lancer une recherche. Par exemple si l'utilisateur en est à "Pon" et appuie sur "t", avant de lancer la recherche, vérifier si tous les résultats affichés ne commencent pas par "Pont", auquel cas ça ne sert à rien d'envoyer une requête au serveur : on va récupérer les mêmes résultats.
    - éventuellement, renvoyer d'abord les résultats les plus courts, ou les plus pertinents, ou un mix des deux
     
    #7 colonies, 24 Mars 2019
    Dernière édition: 24 Mars 2019
  8. sff
    sff WRInaute impliqué
    Inscrit:
    2 Février 2005
    Messages:
    525
    J'aime reçus:
    0
    Afin de correspondre au premier code et de me faciliter les choses j'ai fais ceci mais ca ne fonctionne pas à cause des doubles apostrophes en début de chaine.

    PHP:
    $sql "SELECT name, zipcode, server FROM cities";

    $requete $bdd -> prepare($sql);
    $requete->execute();

    while (
    $donnees $requete->fetch()) {

         
    $ar[] = "'".$donnees['name']."'";
    }

    $values = [implode(','$ar)];



    if (
    $query) {
        foreach (
    $values as $key => $value) {
            if (
    stripos($value$query) === false) {
                unset(
    $values[$key]);
            }
        }
    }

    echo 
    json_encode(array_values($values));
    £values me donne ceci : ["'mot 1','mot 2','mot 3'"] et je souhaite avoir cela : ['mot 1','mot 2','mot 3'] comme sur le premier code.
     
Chargement...
Similar Threads - Autocomplete php 36000 Forum Date
Jquery autocomplete et liens Développement d'un site Web ou d'une appli mobile 6 Juin 2013
Sélection automatique du dernier élément de liste avec autocomplete Développement d'un site Web ou d'une appli mobile 12 Septembre 2012
Alléger le trafic du à un autocomplete Développement d'un site Web ou d'une appli mobile 15 Février 2011
[PHP] Détecter le navigateur / bot en fonction du HTTP_USER_AGENT Développement d'un site Web ou d'une appli mobile 14 Septembre 2019
PHP : checkdnsrr (MX) et domaine yahoo.fr Développement d'un site Web ou d'une appli mobile 5 Septembre 2019
Migration site PHP vers Gatsby : quelques questions Problèmes de référencement spécifiques à vos sites 22 Août 2019
Rediriger sujet phpBB3 vers Vanilla 3 URL Rewriting et .htaccess 6 Août 2019
JS Ajax PHP e-MAIL Développement d'un site Web ou d'une appli mobile 17 Juin 2019
récupérer id en php sans lien Développement d'un site Web ou d'une appli mobile 25 Avril 2019
Erreur PHP Fatal error: Allowed memory size of ... bytes exhausted Demandes d'avis et de conseils sur vos sites 23 Mars 2019
  1. Ce site utilise des cookies. En continuant à utiliser ce site, vous acceptez l'utilisation des cookies.
    Rejeter la notice