Localiser une IP en php
Résolu
Herve_be
Messages postés
1182
Date d'inscription
Statut
Membre
Dernière intervention
-
Herve_be Messages postés 1182 Date d'inscription Statut Membre Dernière intervention -
Herve_be Messages postés 1182 Date d'inscription Statut Membre Dernière intervention -
Bonjour,
Je trouve des réponses sur https://forums.commentcamarche.net/forum/ mais elles ne sont pas récentes; j'en ai essayé quelques unes : soit ça ne fonctionne pas du tout, soit le nombre d'interrogations est limité, ...
Bref, comment obtenir le pays et si possible la ville correspondants à une adresse IP ?
Merci
Je trouve des réponses sur https://forums.commentcamarche.net/forum/ mais elles ne sont pas récentes; j'en ai essayé quelques unes : soit ça ne fonctionne pas du tout, soit le nombre d'interrogations est limité, ...
Bref, comment obtenir le pays et si possible la ville correspondants à une adresse IP ?
Merci
32 réponses
- 1
- 2
Suivant
Résumé de la discussion
L’objectif est d’obtenir le pays et la ville correspondants à une adresse IP via GeoIP en PHP, en évaluant différentes implémentations et bibliothèques et en s’appuyant sur des solutions discutées en ligne. Des échanges portent sur l’utilisation de la directive use pour les namespaces GeoIP2 ou GeoIP, sur les soucis liés à l’installation via Composer et sur l’erreur fatale lorsque le fichier GeoLite2-City.mmdb est absent ou illisible. D'autres échanges décrivent des stratégies pour éviter les exceptions non capturées, comme tester l’IP et conditionner l’appel au lecteur, ou utiliser une nouvelle variable plutôt que de réutiliser $IP pour stocker le résultat.
-
Bonjour,
Tu peux utiliser les bases GeoIP mises à disposition par Maxmind.
Pour les télécharger il faut s'inscrire sur le site de Maxmind :
https://dev.maxmind.com/geoip/geoip2/geolite2/
Pour les utiliser tu as une lib officielle, tout est expliqué avec des exemples :
https://github.com/maxmind/GeoIP2-php
Un rapide exemple fonctionnel, à adapter :
(j'utilise les ternaires de PHP7, à transformer en ternaire classique sur les anciennes versions)<?php // dépendances require_once 'vendor/autoload.php'; use GeoIp2\Database\Reader; // choix de la base, GeoLite2-City contient les villes (City) // sinon Geolite2-Country.mmdb suffit pour les pays $reader = new Reader('GeoLite2-City.mmdb'); // choix d'une IP $record = $reader->city("195.248.251.112"); print( // country->names['code-pays'], nom localisé ($record->country->names['fr'] ?? "Pays introuvable") . '<br/>' . // idem, peut retourner NULL, j'anticipe avec une ternaire ($record->city->names['fr'] ?? "Ville introuvable") ); ?>
Résultat :France
Paris -
Merci pour ta réponse,
J'avais trouvé un tuto ici http://www.finalclap.com/faq/8-php-geolocalisation-ip
Je suis bloqué parce qu'il est écrit "extraire le zip téléchargé pour récupérer le fichier GeoLiteCity.dat"
j'ai téléchargé et décompressé GeoLite2-City mais le fichier que je trouve s'appelle "GeoLite2-City.mmdb"
où dois-je le mettre pour que ton exemple fonctionne ? -
Comme tu veux, il faudra simplement adapter
new Reader('GeoLite2-City.mmdb');pour indiquer l'emplacement du fichier.
Dans mon exemple c'était dans le même dossier, sinon tu devras indiquer le chemin (relatif ou absolu, c'est toi qui décide !).
-
OK, j'ai mis la DB dans le même répertoire que mon script php qui va l'utiliser.
C'est sympa de vouloir m'aider.
En plus de Databse/Reader de quels autres fichiers ai-je besoin du répertoire src ?
Dans ton script je ne comprends pas vendor/autoload.php -
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question -
Toutes les instructions d'installation sont sur la page github. Ils disent vraiment quel fichier inclure et comment.
https://github.com/maxmind/GeoIP2-php#readme
Moi j'ai suivi l'étape "Composer", donc dans le dossier du projet :composer require geoip2/geoip2:~2.0
Si tu n'as pas composer je te renvois (encore) aux explications du github pour savoir comment l'installer.
Tu peux aussi suivre l'autre solution et utilisergeoip2.phar
, à récupérer sur leur github (les explications, encore :P).
Il te suffira alors de remplacer :require_once 'vendor/autoload.php'; use GeoIp2\Database\Reader;
par :require 'geoip2.phar'; use GeoIp2\Database\Reader;
Mes explications s'arrêtent ici, tu as vraiment tout ce qu'il faut pour réussir à utiliser GeoIP. Je te renvois également à l'image que j'ai posté plus haut, et qui est simplement un screen de mon dossier de test.
(et il faut lire le github :P) -
J'ai téléchargé Composer-setup.exe pour essayer d'installer Composer.
L'installeur me demande un fichier php.exe
Je pense que je vais laisser tomber. -
yg_be Messages postés 23437 Date d'inscription Statut Contributeur Dernière intervention Ambassadeur 1 588
bonjour, moi, sur mon site, pour les adresses ipv4, je retrouve l'info via la variable globale $_SERVER:
[GEOIP_CITY] =>
[GEOIP_COUNTRY_NAME] => -
J'essaye d'essayer avec GeoIP2.phar
J'ai créé un répertoire GeoIP à la racine dans lequel j'ai mis la DB, geoip2.phar
ainsi que les répertoires Database, Exception, ...
et donc puisqu'il est à la racine
use /GeoIp\Database\Reader;
mais il n'aime pas le '/' -
-
Je n'ai pas de serveur local.
-
Cette fois c'est à toi de t'adapter, je ne peux pas te proposer toutes les solutions possibles sans même savoir comment tu peux tester ton code PHP. Je précise par ailleurs que n'importe quel tuto PHP à destination des débutants te dira d'installer un simple serveur Wamp pour tester ton code facilement.
Donc soit tu installes un serveur local pour coller à mes instructions, soit tu fait comme je t'ai dit plus haut, avecgeoip2.phar
à mettre simplement dans le même dossier.<?php // dépendances require 'geoip2.phar'; use GeoIp2\Database\Reader; // choix de la base, GeoLite2-City contient les villes (City) // sinon Geolite2-Country.mmdb suffit pour les pays $reader = new Reader('GeoLite2-City.mmdb');
En faisant comme je t'ai dit, avec le code que je t'ai donné dans mon premier message, tu n'as aucune raison d'être bloqué. -
Je trouve un peu lourd de devoir installer un serveur local pour pouvoir installer Composer pour pouvoir utiliser autoload.php pour pouvoir obtenir la localisation d'une adresse IP.
Il me semble plus simple d'utiliser geoip2.phar mais je dois mettre aussi dans le même répertoire Database\Reader et GeoLite2-City.mmdb et peut-être aussi d'autres fichiers.
En d'autres termes pour chaque script php où je veux localiser l'IP je devrais duplicier tous ces fichiers dans le même répertoire.
N'est-il pas possible de mettre une seule fois ce fichiers dans un répertoire commun afin de pouvoir les invoquer à partir de n'importe quel script php ?-
- Parce que, comme je l'ai écrit avant, j'ai créé un répertoire GeoIP à la racine dans lequel j'ai mis la DB, geoip2.phar
ainsi que les répertoires Database, Exception, ... et donc puisqu'il est à la racine
use /GeoIp\Database\Reader;
mais il n'aime pas le '/'
Je viens cependant de comprendre que pour atteindre la racine en php il ne faut pas utiliser '/' comme en html mais $_SERVER['DOCUMENT_ROOT'], ce problème devrait donc être réglé.
-
-
Une possibilité serait de mettre un script php ainsi que la DB dans un répertoire distinct
d'appeler ce script en lui passant l'IP comme paramètre
et qu'il retourne comme paramètre par exemple la ville et le pays.
Dans un répertoire GeoIP situé à la racine je mets la DB, le reader, ... et un script php que j'appelle LocateIP<?php session_start(); require 'geoip2.phar'; use GeoIp2\Database\Reader; $reader = new Reader('/GeoIP/GeoLite2-City.mmdb'); $result = json_decode(file_get_contents('http://ip-api.io/json/'.$_SESSION['LocateIP']),true); extract($result); $_SESSION['LocateIP'] = $city."/".$region_name."/".$country_name; ?>
Pour l'appeler à partir de n'importe quel répertoiresession_start(); $_SESSION['LocateIP'] = l'IP à localiser $output = shell_exec ( '\GeoIP/LocateIP.php' ); $_SESSION['LocateIP'] contient le nom de la ville, région, pays
Problème : Warning: shell_exec() has been disabled for security reasons
Je n'ai pas de disable_functions dans php.ini ! -
Ai-je oublié quelque chose ?
require $_SERVER['DOCUMENT_ROOT'].'GeoIP/geoip2.phar'; use $_SERVER['DOCUMENT_ROOT'].GeoIP\Database\Reader; $reader = new Reader($_SERVER['DOCUMENT_ROOT'].'GeoIP/GeoLite2-City.mmdb'); $result = json_decode(file_get_contents('http://ip-api.io/json/'.$IP),true); extract($result); $Location = $city."/".$region_name."/".$country_name;-
je ne comprends pas ce que tu essaies de réaliser. as-tu lu la suggestion en #1?
-
-
bonjour,
En effet je ne sais plus d'où ça sort, reset.
Le répertoire GeoIP situé à la racine de mon espace web contient en principe les répertoires et fichiers nécessaires pour utiliser GeoIP2.
Je rencontre toujours des difficultés pour l'utiliser à partir d'un autre répertoire; voici mon code<?php // dépendances GeoIP require $_SERVER['DOCUMENT_ROOT'].'/GeoIP/geoip2.phar'; use GeoIP\Database\Reader; $reader = new Reader('GeoLite2-City.mmdb'); ... $record = $reader->city($IP); // $IP contient l'IP que je veux localiser $Location = ($record->city->names['fr'] ?? "Ville introuvable")."/".($record->country->names['fr'] ?? "Pays introuvable");
Fatal error: Uncaught Error: Class 'GeoIP\Database\Reader' not found
Comment expliquer à Use que GeoIP se trouve à la racine ? -
Use sert à définir un alias pour un Namespace.
Puisque mon répertoire s'appelle GeoIP et non GeoIP2 j'avais remplacé
use GeoIP2\Database\Reader;
par
use GeoIP\Database\Reader;
Comme en #1
use GeoIp2\Database\Reader;
Fatal error: Uncaught InvalidArgumentException: The file "GeoLite2-City.mmdb" does not exist or is not readable. in phar:///customers/e/a/4/rudyv.be/httpd.www/GeoIP/geoip2.phar/vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php:52 Stack trace: #0 phar:///customers/e/a/4/rudyv.be/httpd.www/GeoIP/geoip2.phar/src/Database/Reader.php(54): MaxMind\Db\Reader->__construct('GeoLite2-City.m...') #1 /customers/e/a/4/rudyv.be/httpd.www/Aquarium/RVRT/RVRTactivityGeoIP.php(6): GeoIp2\Database\Reader->__construct('GeoLite2-City.m...') #2 {main} thrown in phar:///customers/e/a/4/rudyv.be/httpd.www/GeoIP/geoip2.phar/vendor/maxmind-db/reader/src/MaxMind/Db/Reader.php on line 52
GeoLite2-City.mmdb se trouve pourtant bien dans le répertoire GeoIP qui est à la racine. -
Merci, c'était ça, mon code complet
require $_SERVER['DOCUMENT_ROOT'].'/GeoIP/geoip2.phar'; use GeoIp2\Database\Reader; $reader = new Reader($_SERVER['DOCUMENT_ROOT'].'/GeoIP/GeoLite2-City.mmdb'); ... $record = $reader->city(trim($IP)); $Location = ($record->city->names['fr'] ?? "Ville?")."/".($record->country->names['fr'] ?? "Pays?");
Il fonctionne presque, je n'ai pas toujours la ville.
Un défaut est que la variable $IP ne contient pas toujours une IP; dans ce cas j'ai une erreur "Uncaught InvalidArgumentException".
Est-il possible que $reader->city(trim($IP)) donne un code d'erreur dans ce cas ? -
J'ai trouvé filter_var($IP, FILTER_VALIDATE_IP)
Un tout grand merci à yg_be et Pyraah-
Merci à yg_be d'avoir pris le relais, j'ai été peu disponible ces derniers jours.
Pour la ville... j'avais précisé dans mon code que ça pouvait renvoyer NULL.
Pour l'IP tu peux d'abord vérifier'REMOTE_ADDR'
. Si c'est vide, vérifie'HTTP_X_FORWARDED_FOR'
.
Dans mon code j'ai chaîné ça dans une suite de ternaires :$ip = $_SERVER['REMOTE_ADDR'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? FALSE;
Je te renvois au timecode suivant, Grafikart explique assez bien les ternaires de PHP7 : https://youtu.be/obr7pO7_myI?t=540
Bye :).
-
-
Bonjour,
J'ai été amené à localiser un IP parce que je constatais une forte utilisation d'un de mes scripts php; j'ai ajouté $_SERVER['REMOTE_ADDR'] pour obtenir l'IP : Washington !
Depuis j'ai ajouté un Captcha au script, problème résolu.
J'ai toutefois gardé l'affichage de l'IP, il est plus pratique d'obtenir directement la localisation plutôt que l'IP, une grand précision n'est pas requise, ça fonctionne très bien comme cela.
Le seul petit problème est qu'au moment de l'affichage je ne suis plus en connexion avec l'utilisateur, j'ai seulement une zone IP dans une DB, et cette zone ne contient pas toujours une IP; dans ce cas $reader->city(trim($IP)) donne "Uncaught InvalidArgumentException" et le script s'arrête.
J'ai alors utilisé filter_var($IP, FILTER_VALIDATE_IP) avant de soumettre la variable à $reader
mais je suis tombé sur un enregistrement où la zone IP contenait "0.0.0.0" qui est une IP syntaxiquement valide, qui passe donc à travers le filtre, mais qui plante le reader avec un message du style "IP not found in GeoLite2-City.mmdb".
Ma question est donc : comment empêcher reader de se planter s'il n'aime pas l'IP qu'on lui passe ?-
connais-tu ceci? https://www.php.net/manual/fr/language.exceptions.php
-
-
Bonjour,
Non, je ne connais pas.
Si j'ai bien compris il faut lancer (throw) l'exception dans le module qui va la produire, à savoir Reader.
Je ne vois pas comment je pourrais m'en servir pour ne pas avoir "Uncatched exception".
Si Reader ne donne pas de réponse mon script peut très bien continuer.
Pour le moment je n'appelle simplement pas le reader si l'IP = "0.0.0.0" ou si filter_var($IP, FILTER_VALIDATE_IP) = false.
- 1
- 2
Suivant


