Pré-requis

La meilleure solution à ce jour me semble être l'utilisation de la base GeoLite city. Elle comporte 2 fichiers csv qu'il faut importer dans les tables suivantes:

Table de géolocalisation

Champ               Index                  Commentaire
startIpNum          Index                  Première IP numérique
endIpNum            Index                  Dernière IP numérique
locId                                      ID du lieu

StartIpNum et endIpNum sont les adresses IP converties en valeur numérique. La méthode de conversion est, si on considère une IP sous la forme AAA.BBB.CCC.DDD: (AAA * 256^3) + (BBB * 256^2) + (CCC * 256) + DDD

Table des villes

Champ                Index                  Commentaire
locId                Primaire               ID du lieu
country              Index                  Pays
region                                      Région administrative
city                                        Ville
postalCode                                  Code postal
latitude             Index                  Latitude
longitude            Index                  Longitude
metroCode
areaCode

Les bases sont assez grosses, donc si vous savez d'avance quels pays vous ciblez, n'hésitez pas à les réduire à ces pays.

Géolocalisation:

Pour retrouver la localisation d'une personne par son IP, il suffit d'une simple requête SQL qui utilisera l'IP transformée:

<?php
/**
 * Fonction retournant les informations géographiques
 *@param string $ip IP du visiteur
 *@return array Tableau contenant la ville et ses coordonnées GPS
 */
function geoloc($ip) {
	// Conversion de l'IP littérale en IP numérique
	$tmp = explode('.', $ip);
	$ipnum = ($tmp[0]*pow(256,3)) + ($tmp[1]*pow(256,2)) + ($tmp[2]*256) + $tmp[3];
	// Requête sur les deux tables pour retourner les informations
	$query = "SELECT c.city, c.latitude, c.longitude
	FROM geo_ip i
	JOIN geo_city c ON (c.locId=i.locID)
	WHERE ".$ipnum." BETWEEN startIpNum AND endIpNum
	LIMIT 1 OFFSET 0";
	$res = mysql_query($query);
	// Retour des informations (ou d'un tableau vide
	if (mysql_num_rows($res) == 0) return;
	return mysql_fetch_assoc($res);
}
// Récupération de l'IP du visiteur
$ip = $_SERVER['REMOTE_ADDR'];
$user = geoloc($ip);
?>

Comme vous pouvez le constater, le système est très simple à mettre en place et donne des résultats viables dans 99% des cas.