Partage
  • Partager sur Facebook
  • Partager sur Twitter

Autocomplet ville

    6 avril 2020 à 15:16:20

    Salut tout le monde,

    J'utilisé jusqu'à présent lapi de google mais je souhaite changé pour différentes raisons.

    J'ai donc recherché un peu et adapté un code selon mes besoin et ma bdd, tout marche .

    J'aimerais juste que quand on saisie 'st' ou saint' cela nous propose quand même la ville et pas uniquement l'orthographe exacte qu'il y a en bdd

    comme 'saint martin d'hères' ou 'st martin d'hères'

    Cote requete pour allé piocher dans la bdd:

    <?php
    function connect() {
        return new PDO('mysql:host=localhost;dbname=listing', 'root', '', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
    }
    
    $pdo = connect();
    $keyword = '%'.$_POST['keyword'].'%';
    $sql = "SELECT DISTINCT Libelle_acheminement FROM villes_de_france WHERE Libelle_acheminement LIKE (:keyword) ORDER BY Libelle_acheminement ASC LIMIT 0, 10";
    $query = $pdo->prepare($sql);
    $query->bindParam(':keyword', $keyword, PDO::PARAM_STR);
    $query->execute();
    $list = $query->fetchAll();
    foreach ($list as $rs) {
    	// put in bold the written text
    	$select_ville = str_replace($_POST['keyword'], '<b>'.$_POST['keyword'].'</b>', $rs['Libelle_acheminement']);
    	// add new option
        echo '<li onclick="set_item(\''.$rs['Libelle_acheminement'].'\')">'.$select_ville.'</li>';
    }
    ?>
    

    Coté js:

    function autocomplet() {
    	var keyword = $('#country_id').val();
    	$.ajax({
    		url: 'ajax_refresh.php',
    		type: 'POST',
    		data: {keyword:keyword},
    		success:function(data){
    			$('#country_list_id').show();
    			$('#country_list_id').html(data);
    		}
    	});
    }
    
    // set_item : this function will be executed when we select an item
    function set_item(item) {
    	// change input value
    	$('#country_id').val(item);
    	// hide proposition list
    	$('#country_list_id').hide();
    }




    • Partager sur Facebook
    • Partager sur Twitter
      6 avril 2020 à 15:44:27

      Bonjour,

      Je n'ai jamais trouvé de solution simple à ce problème.

      Ce que je fais ...

      Dans ton référentiel - donc pour l'instant je ne suis pas au niveau de la recherche - d'abord j'élimine tous les mots non significatifs appelés stopword in english - le, la, d' (c'est ton cas) etc puis je prends le restant que je mets strictement en minuscule non accentué et je considère que ce sont des mots clefs que j'associe au libellé complet. Un ensemble de keyword en base associé au libellé complet (je ne fais pas la modélisation).

      Donc par exemple dans ton cas, ce pourrait être 'saint martin heres' avec heres sans accent.

      Lors de la recherche, on applique le même algo et on compare sur les mots clefs.

      Si on veut aller plus loin par exemple la personne qui saisit 'Saint Martin Here' sans s alors soit tu considères que 2 mots justes sur 3 suffisent soit tu te lances dans la phonémisation.

      Comme je te disais pas de solution simple.

      Dernier truc que je fais encore plus complexe et complémentaire, tu ajoutes de l'intelligence artificielle. Bon juste pour trouver des villes je ne pense pas que cela vaille le coup.

      Mais c'est assez fun et possible en php sans passer par Google et consort : https://github.com/php-ai

      A+

      -
      Edité par monkey3d 6 avril 2020 à 17:02:12

      • Partager sur Facebook
      • Partager sur Twitter
        6 avril 2020 à 16:20:02

        Je me serais "machinalement" orienté sur du fulltext même si ça paraît un peu overkill de prime abord. Et avec MySQL, déjà, si la colonne a un interclassement insensible à la casse et aux accents ça te fait déjà ça de moins à gérer (indépendamment de l'usage d'un fulltext ou non).

        Normalement, les mots de moins de 3 lettres sont automatiquement exclus et au pire, tu dois pouvoir définir ta propre liste de stopword. Par contre, apparemment, il n'y a pas moyen de définir des équivalences de mots (type st = saint). Donc tu normalises via une colonne dédiée (indexée ) aussi bien ce que tu insères que la saisie utilisateur (type preg_replace('~\bst(e)?\b~i', 'saint\1', ...) et autre truc du genre).

        Quoi qu'il en soit, AMHA, LIKE n'est pas du tout approprié, surtout comme ça, sans découpage en "mots". Dans le meilleur des cas ça permettra juste de retrouver une ville qui contient ce qui est cherché, ça risque d'être pas vraiment pertinent, tu ne peux pas non plus trier par pertinence, ce n'est pas efficace. L'avantage du fulltext sur like, c'est que tu peux le faire évoluer à bien des égards vu toute la panoplie d'options en tout genre à disposition.

        Ceci dit c'est plus un avis personnel qu'autre chose. Tout dépend aussi jusqu'où tu veux pousser ta fonctionnalité et de ton public, celui qui se doute que ça fonctionne avec un LIKE derrière aura probablement l'idée de chercher à partir de la sous-chaîne la plus significative du nom de la ville contrairement à un néophyte/non-informaticien.

        PS : les caractères % et _, pour un LIKE, devrait être échappés

        -
        Edité par julp 6 avril 2020 à 16:32:46

        • Partager sur Facebook
        • Partager sur Twitter
          6 avril 2020 à 17:58:18

          J'ai des système plus ou moins tout fait mais rien qi me convient,

          J'ai pensé a stocké dans un array mais bon c'est énorme 38000 Communes

          J'ai trouvé vicopo, je tenais à partager ca avec vous pour le coup

          il gére le fameux problème des ' ou saint ou st

          Mais avec ce script j'ai un nouveau problème si on tape: Lyon:

          Il propose tous les code postaux de lyon qui correspondent aux arrondissement, problème identique pour paris et marseille forcèment, si je pouvais limiter à seulement la ville principale enfin voilà pour ceux qui cherche comme moi vous avez éventuellement:

          https://vicopo.selfbuild.fr/

          Pour les motivés le js on doit se faire la manip en question du saint et st mais perso ce n'est pas ma tasse de thé:

          jQuery(function ($) {
              var _code = $('#code'), _city = $('#city'), _out = $('#output');
              var _cache = {};
              var _protocol = ~(location.protocol + '').indexOf('s') ? 'https' : 'http';
              var _host = _protocol + '://vicopo.selfbuild.fr';
              _code.keyup(function () {
                  var _val = $(this).val();
                  if (/^[^0-9]/.test(_val)) {
                      _code.val('');
                      _city.val(_val).focus().trigger('keyup');
                  }
              });
              _city.keyup(function () {
                  var _val = $(this).val();
                  if (/^[0-9]/.test(_val)) {
                      _city.val('');
                      _code.val(_val).focus().trigger('keyup');
                  }
              });
              function _done(_cities) {
                  _out.html(_cities.map(function (_data) {
                      return '<a href="#">' + _data.code + ' &nbsp; ' + _data.city + '</a>';
                  }).join(''));
              }
          
              $.each(['city'], function (i, _name) {
                  var _input = $('#' + _name).on('keyup', function () {
                      var _val = _input.val();
                      if (_val.length > 1) {
                          _cache[_name] = _cache[_name] || {};
                          if (_cache[_name][_val]) {
                              _done(_cache[_name][_val]);
                          }
                          var _data = {};
                          _data[_name] = _val;
                          $.getJSON(_host, _data, function (_answear) {
                              _cache[_name][_answear.input] = _answear.cities;
                              if (_input.val() == _answear.input) {
                                  _done(_answear.cities);
                              }
                          });
                      }
                  });
              });
              $(document).on('click', '#output a', function (e) {
                  var _contents = $(this).text();
                  var _space = _contents.indexOf(' ');
                  if (~_space) {
                      _code.val(_contents.substr(0, _space));
                      _city.val(_contents.substr(_space).trim());
                      _out.empty();
                  }
                  e.preventDefault();
                  e.stopPropagation();
                  return false;
              });
          });
          



          -
          Edité par blinz 6 avril 2020 à 18:22:48

          • Partager sur Facebook
          • Partager sur Twitter
            6 avril 2020 à 18:20:45

            J'ai des système plus ou moins tout fait mais rien qi me convient,

            Tu veux dire que ce que l'on te propose Julp et moi ne te convient pas ?

            Pourquoi vouloir stocker toutes les communes dans un array ?

            Ma solution fonctionne mais si elle ne convient pas cela ne me fâche pas.  :D

            A+ ou bye

            EDIT : ton lien est intéressant mais moi je n'aime pas ces api dont on ne sait pas trop ce qu'elles font des données envoyées.

            -
            Edité par monkey3d 6 avril 2020 à 18:33:24

            • Partager sur Facebook
            • Partager sur Twitter
              6 avril 2020 à 18:30:56

              Non bien sur c'est même parfait,

              Je n'ai juste pas les compétences pour codé cela mais ta solution été très bien.

              Je vais essayer de me pencher dessus malgré tout.

              J'ai une petite fonction qui me permet de "sluger une chaine"

              Que je traite ainsi dans ma page si on saisie une ville et qu'on l'envoi alors je slug et redirige

              if(!empty($_POST['ville'])) { header('Location: commercants-'.simplification($_POST['ville']).'.html'); } // ville

              Ma fonction:

              	// Simplifier une chaine
              	function simplification($chaineNonValide, $separator='-') {
              		
              		$chaineNonValide = strip_tags(html_entity_decode($chaineNonValide));	
              		
              		$accented = array("-",'&','À','Á','Â','Ã','Ä','Å','Æ','Ă','Ą','Ç','Ć','Č','Œ','Ď','Đ','à','á','â','ã','ä','å','æ','ă','ą','ç','ć','č','œ','ď','đ','È','É','Ê','Ë','Ę','Ě','Ğ','Ì','Í','Î','Ï','İ','Ĺ','Ľ','Ł','è','é','ê','ë','ę','ě','ğ','ì','í','î','ï','ı','ĺ','ľ','ł','Ñ','Ń','Ň','Ò','Ó','Ô','Õ','Ö','Ø','Ő','Ŕ','Ř','Ś','Ş','Š','ñ','ń','ň','ò','ó','ô','ö','ø','ő','ŕ','ř','ś','ş','š','Ţ','Ť','Ù','Ú','Û','Ų','Ü','Ů','Ű','Ý','ß','Ź','Ż','Ž','ţ','ť','ù','ú','û','ų','ü','ů','ű','ý','ÿ','ź','ż','ž','А','Б','В','Г','Д','Е','Ё','Ж','З','И','Й','К','Л','М','Н','О','П','Р','а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я');
              		$replace = array("-",'et','A','A','A','A','A','A','AE','A','A','C','C','C','CE','D','D','a','a','a','a','a','a','ae','a','a','c','c','c','ce','d','d','E','E','E','E','E','E','G','I','I','I','I','I','L','L','L','e','e','e','e','e','e','g','i','i','i','i','i','l','l','l','N','N','N','O','O','O','O','O','O','O','R','R','S','S','S','n','n','n','o','o','o','o','o','o','r','r','s','s','s','T','T','U','U','U','U','U','U','U','Y','Y','Z','Z','Z','t','t','u','u','u','u','u','u','u','y','y','z','z','z','A','B','B','r','A','E','E','X','3','N','N','K','N','M','H','O','N','P','a','b','b','r','a','e','e','x','3','n','n','k','n','m','h','o','p','C','T','Y','O','X','U','u','W','W','b','b','b','E','O','R','c','t','y','o','x','u','u','w','w','b','b','b','e','o','r ');
              		$chaineValide = str_replace($accented, $replace, $chaineNonValide);
              		
              		$search = array ('@[ ]@i','@[^a-zA-Z0-9_-]@');
              		$replace = array ($separator, '');
              		$chaineValide = preg_replace('/(?:(['.$separator.'])\1)\1*/', '$1', trim(strtolower(preg_replace($search, $replace, $chaineValide)), $separator));
              		
              	return $chaineValide;
              				
              	}

              Si ça peut servir à quelqu'un au passage


              -
              Edité par blinz 6 avril 2020 à 18:33:11

              • Partager sur Facebook
              • Partager sur Twitter
                6 avril 2020 à 18:35:36

                Ma solution est sans doute un peu complexe à mettre en oeuvre mais elle est faite pour traiter un problème un peu plus global de conversation avec un assistant en mode texte ... d'où à la fin le coup de l'IA.

                Si travailler avec une API ne te dérange pas, let's go.

                Bye

                -
                Edité par monkey3d 6 avril 2020 à 18:36:07

                • Partager sur Facebook
                • Partager sur Twitter

                Autocomplet ville

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown