Base de données des villes, régions, départements de France et carte interactive

Dans le cadre de développement d'un site web, d'un annuaire, d'une application ou d'un simple formulaire il est assez fréquent de demander une adresse postale. Le fait de posséder une base de données des villes de France peut s'avérer utile et pratique, on peut alors en ressortir des statistiques par régions, départements et villes.

Ce que propose ce tutoriel :

  • Intégration d'une base de données des villes de France. (MySQL)
  • Affichage dynamique des villes suivant le code postal (PHP + JavaScript)
  • Navigation par carte interactive (Flash)
  • Navigation par menu accordéon (JQuery)

Je ne détaillerais pas volontairement les parties sur l'AJAX ou l'intégration de googlemap afin de ne pas alourdir le tuto.

J'ai pour cela utilisé une base de données comportant 34500 villes. En France il y en a un peu plus de 36 000 donc il faut prévoir qu'une ville n'est pas enregistrée et le cas échéant proposer un champ libre.

Ce qui peut s'avérer utile également est d'obtenir les positions GPS des villes.
Pour cela on va utiliser l'API de googlemap, il faut au préalable vous munir d'une clé d'accès.

Il suffit ensuite en théorie de boucler toute la table en interrogeant l'API Google, le problème est que c'est assez lourd et vous risquez d'obtenir quelques erreur sur la durée d'exécution du script. On vas régler ce problème avec une limite de temps et une redirection JavaScript qui rechargeras notre page toutes les 120 secondes avec une pause de 30 secondes entre chaque rechargement pour notre exemple.

J'ai mis une pause de 30 secondes parce que j'ai un doute sur le nombre de requêtes à la minute autorisé par googlemap.

La base de données

Il y a 3 tables SQL la table des régions, la table des départements et la table des villes (on aurait pu ajouter une table des pays, mais restons simple).

Voici le schéma des tables

Structure de la Base de données

De cette façon on pourra remonter à partir d'une ville jusqu'à la région. Ou à partir d'une région obtenir la liste des départements et des villes.


$timedeb = time() ; // timestamp au début du chargement du script

// INTEGRATION DE L'API

require('GoogleMapAPI.class.php'); // on incluse l'api de googlemap
$map = new GoogleMapAPI('map','');
$map>setAPIKey('VOTRE_CLEF');

// REQUETE MYSQL

// on sélectionne tous les enregistrements qui n'ont pas de latitude ou de longitude

$selville = mysql_query("SELECT * FROM maps_ville WHERE lat='' OR long='' ");
while($ville=mysql_fetch_array($selville)) {
$coord = $map->geoGetCoords($ville['cp'].','.$ville['nom']); // on obtient la latitude et la longitude
if(!empty($coord['lat']) || !empty($coord['lon'])) {
// on met a jour l'enregistrement avec les nouvelles valeurs.
mysql_query("UPDATE maps_ville SET lat='".$coord['lat']."', lon='".$coord['lon']."' WHERE id_ville='".$ville['id_ville']."'");
}else{

// on remplit avec une valeur de 0 si aucune coordonnées as été trouvé pour éviter que le script tourne sans fin

mysql_query("UPDATE maps_ville SET lat='0', lon='0' WHERE id_ville='".$ville['id_ville']."'");
}

$timefin = time(); // on vérifie le timestamp

// si le temps entre le timestamp du début et le timestamp de fin est supérieur a 120 secondes alors on fait une pause de 30 secondes.

if($timefin-$timedep>120) {
sleep(30);

// code javascript de rechargement de la page

?>
<SCRIPT LANGUAGE="JavaScript">
document.location.href="villegps.php"
</script>

Bon voilà ce que j'ai employé pour récupérer les coordonnés GPS, inutile de le faire puisque la base de données est fourni avec les coordonnées.

Passons aux choses plus intéressantes.

Dans un formulaire...

On veut afficher la liste des villes correspondant à un code postal saisie le tout en Ajax.

Notre champ ce comporte de la façon suivante.

A chaque relâchement de touche on va exécuter notre fonction afficheVille.


Code postal :
<input type="text" size="5" length="5" maxlength="5" name="cp" onKeyUp="afficheVille(this.size, this.value)"/>
<span id="listeville"></span>

La fonction javascript afficheVille


function afficheVille(size, cp) {
if (cp.length > size-1) {
maRequete.request("action=affVille&codepostal="+cp);
}
}

On vérifie si la longueur du champ est complétée (5 chiffres) si elle l'est on lance notre requête AJAX. Ce qui donne pour le code javascript complet ceci :


<script language="javascript>
function afficheVille(size, cp) {
if (cp.length > size-1) {
maRequete.request("action=affVille&codepostal="+cp);
}
}

maRequete=new loader("ajax_carte.php");

function loader(url){
this.url=url;
if(typeof XMLHttpRequest!="undefined"){this.http=new XMLHttpRequest();
}else if(typeof ActiveXObject!="undefined"){
this.http=new ActiveXObject("MSXML2.XmlHttp");
}else{
alert("No XMLHttpRequest object available. This functionality will not work.");
}
}

loader.prototype.request=function(postReq){
var oHttp=this.http;
if (oHttp.readyState!=0){oHttp.abort();}
oHttp.open("POST",this.url,true);
oHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
oHttp.onreadystatechange=function(){
if (oHttp.readyState==4){

var reponsePHP=oHttp.responseText;

window.eval(reponsePHP);

} else {

//document.getElementById("chargement").innerHTML = "<img src='images/ajax-loader.gif' alt=''/>Chargement en cours ...
";
}
};
oHttp.send(postReq);
};
// -->
</script>

Traitement de la requête AJAX.

Tout ce passe dans le fichier ajax_carte.php

On va utiliser un Switch car d'autre fonction viendront se greffer dans ce fichier (ajout d'une ville, affichage d'un champ libre, etc.)

< ?php
switch($_POST['action']) {

case 'affVille':
afficheVille();
break;

}

function afficheVille() {
$aff_ville = 'Ville : <select name="ville">';
$selville = mysql_query("SELECT nom FROM maps_ville WHERE cp='".$_POST['codepostal']."' ");
while($ville=mysql_fetch_array($selville)) {
$accent = "àáâãäåòóôõöøèéêëçìíîïùúûü";
$sansaccent = "ÀÁÂÃÄÅÒÓÔÕÖØÈÉÊËÇÌÍÎÏÙÚÛÜ";
$ville = strtr(utf8_encode($ville['nom']),$accent,$sansaccent);
$aff_ville .= '<option value="'.$ville.'" >'.strtoupper($ville).'</option>';
}
$aff_ville .= '</select>';
?>document.getElementById('listeville').innerHTML='<?=$aff_ville?>';<?
}
?>

Donc rien de compliquer on va chercher les villes correspondantes au code postal et on affiche tout ça dans notre span listeville.

Pour un annuaire

La carte de France provient des forums mediabox. Je l'ai simplement retouché pour lui mettre les liens et variables dont on a besoins et changé la carte de fond qui à la base était d'une couleur unie, rien ne vous empêche (et je vous le conseille) de personnaliser votre propre carte. Il suffit seulement de remplacer un masque. Le plus gros travail de découpe des départements a déjà été réalisé.

On peut intégrer un menu accordéon vertical en utilisant la bibliothèque JavaScript JQuery.
Ce qui nous donnera deux sortes de navigation (Carte + menu).

Le code pour créer le menu accordéon


<script type="text/javascript" src="js/jquery-1.2.6.min.js"></script>
<script language="javascript">
<!--
$(document).ready( function () {

// On cache les sous-menus :
$(".navigation ul.subMenu").hide();

// On sélectionne tous les items de liste portant la classe "toggleSubMenu"
// et on remplace l'élément span qu'ils contiennent par un lien :
$(".navigation li.toggleSubMenu span").each( function () {
// On stocke le contenu du span :
var TexteSpan = $(this).text();
$(this).replaceWith('<a href="" title="Afficher le sous-menu">' + TexteSpan + '</a>') ;
} ) ;

// On modifie l'évènement "click" sur les liens dans les items de liste
// qui portent la classe "toggleSubMenu" :
$(".navigation li.toggleSubMenu > a").click( function () {
// Si le sous-menu était déjà ouvert, on le referme :
if ($(this).next("ul.subMenu:visible").length != 0) {
$(this).next("ul.subMenu").slideUp("normal", function () { $(this).parent().removeClass("open") });
}
// Si le sous-menu est caché, on ferme les autres et on l'affiche :
else {

$(".navigation ul.subMenu").slideUp("normal", function () { $(this).parent().removeClass("open") });
$(this).next("ul.subMenu").slideDown("normal", function () { $(this).parent().addClass("open") });
}
// On empêche le navigateur de suivre le lien :
return false;
});

} ) ;
// -->
</script>

Et on liste simplement les régions et départements

<ul class="navigation">
< ?php
$selreg = mysql_query("SELECT * FROM region");
while($reg=mysql_fetch_array($selreg)) {
echo '<li class="toggleSubMenu"><span>'.toutmajuscule($reg['nom_region']).'</span>';
echo '<ul class="subMenu">';
$seldep= mysql_query("SELECT * FROM departement WHERE id_region='".$reg['id_region']."'");
while($dep = mysql_fetch_array($seldep)) {
echo '<li><a href="carte.php?dep='.$dep['code'].'">'.$dep['nom_departement'].'</a></li>';
}
echo '</ul>';
echo '</li>';
}

?>
</ul>

Une petite fonction pour forcer les majuscules sur les caractères accentués.

function toutmajuscule($chaine){
$acc = array('ç','à','á','â','è','é','ê','ò','ó','ô','ù','ú','û','À','Á','Â','È','É','Ê','Ì','Í','Î','Ò','Ó','Ô','Ù','Ú','Û');
$sans = array('C','A','A','A','E','E','E','O','O','O','U','U','U','A','A','A','E','E','E','I','I','I','O','O','O','U','U','U');
$mot = str_replace($acc,$sans,$chaine);
return strtoupper($mot);
}

Pour le carte de France si vous voulez utiliser votre propre page et vos propre nom de variable il suffit de modifier la ligne 57 de l'actionscript

getUrl("./carte.php?dep=" + num, "_self");

Vous pouvez tout à fait intégrer de l'Ajax en y mettent une fonction JavaScript par exemple

getURL("javascript: afficheDep('"+num+"')");

De même pour le menu accordéon.

Et parce que le meilleur moyen d'apprendre pour moi est de passer par la pratique je vous propose d'améliorer et de personnaliser le système et de nous faire part de vos créations.

Par exemple proposer un champ autre dans le menu déroulant des villes qui feras apparaitre un champ libre et qui ensuite enregistrera la ville si elle n'existe pas.

Si vous trouvez d'autres bases de données des villes, d'autres pays par exemple, ajoutez une table pays avec les id_region.

Pour une recherche géographique, afficher les villes dans un rayon de X kilomètre par rapport à une ville de départ (d'où l'utilité des coordonnées GPS dans la table maps_villes).

Intégrer des bases de données d'IP par ville (il est possible de retrouver une ville via une IP) et préremplir un formulaire suivant l'IP du visiteur.

Bref une multitude d'options vous sont permit à partir de code.

Voilà bon codage a tous.

Vous pouvez télécharger les les sources .php, .js, .fla

Dans le forum : Script Carte de france + BDD SQL ville et département

Ne manquez pas les futurs articles via Twitter

A propos de l'éditeur d'Oseox.fr

Aurélien Bardon est un passionné de SEO. Il crée Outil-Referencement.com en 2005, Oseox.fr en 2008, fonde en 2009 l'agence SEO Aseox à Lille et lance en 2016 Oseox Software, une plateforme de logiciels SEO.

Oseox Monitoring