Closed jgarino closed 10 years ago
You will need to install MaxMind DB.
I don't really follow why you can't use Composer as you can download everything before you upload it to your site, but I would at least recommend using some PSR-0 autoloader, even if it just the example version.
Hi, I only use MaxMindDb now and it is enough to parse the CityLite mmdb. Problem solved.
Thanks very much.
Hi jGarino,
How do you install the CityLite mmdb? I have installed composer, but now got error message "Class 'GeoIp2\Database\Reader' not found "
Thanks
Hi,
you can use https://github.com/maxmind/MaxMind-DB-Reader-php component download and use it this way :
require_once 'MaxMind/Db/Reader.php'; require_once 'MaxMind/Db/Reader/Decoder.php'; require_once 'MaxMind/Db/Reader/InvalidDatabaseException.php'; require_once 'MaxMind/Db/Reader/Metadata.php';
use MaxMind\Db\Reader;
$record = NULL; $reader = new Reader($geoip2_uncompressed_database); $record = $reader->get($_SERVER['REMOTE_ADDR']);//any IP var_dump($record);
//I hope this helps !
I haven't used composer at all... Just downloaded the package and use the PHP sources.
This project and its submodule(s) are a mess. It should be standalone just like the Reader should be standalone. Also, the various closed issues need to be addressed in a more sane manner that doesn't indicate that the devs have their fingers in their ears going "lalalalalalala" at the top of their lungs.
Thanks for the code tips and upstream project. I'll forgo this "completely useless" project and use that upstream "just shy of useless" Reader project instead. I much prefer the older GeoIP PHP scripts despite the weird file extensions the MaxMind devs used before (.inc) but those scripts aren't compatible with GeoIP2.
We released a phar archive version of the API for people who don't want to use Composer directly:
@oschwald
Can you give more details on how to use the phar archive? I apologize ahead of time for being a newb when it comes to this as I have never used a phar archive. For instance, using your example and the locations of the phar and mmdb files... how do I make use of this?
vendor/autoload.php & use GeoIp2\Database\Reader; are the obvious problems.
<?php
require '/home/test/public_html/custom/geoip/0.6.0/geoip2.phar';
require_once 'vendor/autoload.php';
use GeoIp2\Database\Reader;
// This creates the Reader object, which should be reused across
// lookups.
$reader = new Reader('/home/test/public_html/custom/geoip/GeoLite2-City.mmdb');
// Replace "city" with the appropriate method for your database, e.g.,
// "country".
$record = $reader->city('128.101.101.101');
print($record->country->isoCode . "\n"); // 'US'
print($record->country->name . "\n"); // 'United States'
print($record->country->names['zh-CN'] . "\n"); // '美国'
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
print($record->city->name . "\n"); // 'Minneapolis'
print($record->postal->code . "\n"); // '55455'
print($record->location->latitude . "\n"); // 44.9733
print($record->location->longitude . "\n"); // -93.2323
?>
Personally, I've given up on using Composer, Phar, etc. For some of us, that's not feasible anyway. I'm using my own code. If you download the right set of source files, you just need to do something like this:
<?php namespace AAABIT;
require_once(HOME_PATH.'/AAABIT_3rdP/GEO/MaxMind/Reader/Decoder.php');//←
require_once(HOME_PATH.'/AAABIT_3rdP/GEO/MaxMind/Reader/InvalidDatabaseException.php');//←
require_once(HOME_PATH.'/AAABIT_3rdP/GEO/MaxMind/Reader/Metadata.php');//←
require_once(HOME_PATH.'/AAABIT_3rdP/GEO/MaxMind/Reader/Util.php');//←
require_once(HOME_PATH.'/AAABIT_3rdP/GEO/MaxMind/Reader.php');//←
function GeoIP(){//Cached GeoLocation from remote client IP address//Makes for convenient coding: simply call e.g.: \AAABIT\GeoIP()->country_iso_code()
static $GeoIP;if(!isset($GeoIP)){$GeoIP=new GeoIP();}return $GeoIP;
}
class GeoIP{
const DB='/MaxMind/GeoLite2-City.mmdb';//
protected static $cityReader,$countryReader;//,$GeoIP;
protected $city,$continent,$country,$registered_country;
protected $postal,$latitude,$longitude,$time_zone,$time_zone_name;
protected $subdivisions;
public function __construct($ip=null,$lang='en'){
if(is_null($ip)){$ip=\Server::REMOTE_ADDR();}
elseif(!filter_var($ip,FILTER_VALIDATE_IP)){throw New Exception('IP address not valid!');}
if(!isset(self::$cityReader)){self::$cityReader=new \MaxMind\Db\Reader(DATA_PATH.self::DB);}
try{ $g=self::$cityReader->get(\Server::REMOTE_ADDR());
$this->city=$g['city'];//if(is_null($this->city)){$this->city=array();}
$this->continent=$g['continent'];
$this->country=$g['country'];
$this->registered_country=$g['registered_country'];
$this->postal=$g['postal'];
$this->subdivisions=$g['subdivisions'];
$this->latitude=$g['location']['latitude'];
$this->longitude=$g['location']['longitude'];
$this->time_zone_name=$g['location']['time_zone'];
if(isset($this->time_zone_name)){$this->time_zone=new \DateTimeZone($g['location']['time_zone']);}//!is_null?
}catch(Exception $e){
} }
private function preferredLang($name_array_assoc){$lang_codes=\array_keys($name_array_assoc['names']);return 'en';}//\LangChooser::preferredLanguage($lang_codes);}
public function city_name(){return $this->city['names'][$this->preferredLang($this->city)];}//GeoLite2-City.mmdb doesn't seem to want to give city details! :-( Same for ZIP codes, obviously.
public function continent_code(){return $this->continent['code'];}
public function continent_geoname_id(){return $this->continent['geoname_id'];}
public function continent_name(){return $this->continent['names'][$this->preferredLang($this->continent)];}
public function country_iso_code(){return $this->country['iso_code'];}//ISO 3166
public function country_geoname_id(){return $this->country['geoname_id'];}
public function country_name(){return $this->country['names'][$this->preferredLang($this->country)];}
public function latitude(){return $this->latitude;}
public function longitude(){return $this->longitude;}
public function time_zone(){return $this->time_zone;}
public function time_zone_name(){return $this->time_zone_name;}
public function registered_country_iso_code(){return $this->registered_country['iso_code'];}
public function registered_country_geoname_id(){return $this->registered_country['geoname_id'];}
public function registered_country_name(){return $this->registered_country['names'][$this->preferredLang($this->registered_country)];}
public function title(){//⋙Should work out the best COMMON LANGUAGE for all elements in this caption! array_intersect etc. This way, will present the whole caption in the same language, for consistency!
$latlong=number_format(abs($this->latitude()),1).'°'.($this->latitude()<0?'S':'N').'; '.number_format(abs($this->longitude()),1).'°'.($this->longitude()<0?'W':'E');//°
return $this->country_name().(is_null($this->city_name())?' ('.$latlong.')':'
'.$this->city_name().' ('.$latlong.')').'
⏰ '.$this->time_zone_name;
}
}
— Obviously, the exact paths will depend on where you decide to put the source and .mmdb files, you will need to define HOME_PATH something like this:
function home_dir(){//UNIX CLI: Server::HOME, WINDOWS CLI: Server::HOMEDRIVE.Server::HOMEPATH, HTTP REQUEST: ???
$matches=array();preg_match('/\/home\/([^\/]*)/',__DIR__,$matches);$home_dir=$matches[0]; //THIS APPROACH should work for Unix/Linux based PHP installations:
// for($p=__DIR__;basename($p)==='htdocs'||basename($p)==='public_html';$p=dirname(p)){} $p=str_replace('\\','/',$p);return dirname($p); //ALTERNATIVE APPROACH:
return $home_dir;
}
define(HOME_PATH,home_dir());
@morrow95 if you remove the require_once 'vendor/autoload.php';
line, your code should work.
Unfortunately it does not - 'Fatal error: Class 'GeoIp2\Database\Reader' not found'.
EDIT : Looks like phar was not enabled on the server by default as it was supposed to be. Sorry for the trouble.
@morrow95, the following works fine for me. Are you sure the path to your geoip2.phar file is correct? What version of PHP are you using?
<?php
require 'geoip2.phar';
use GeoIp2\Database\Reader;
// This creates the Reader object, which should be reused across
// lookups.
$reader = new Reader('GeoLite2-City.mmdb');
// Replace "city" with the appropriate method for your database, e.g.,
// "country".
$record = $reader->city('128.101.101.101');
print($record->country->isoCode . "\n"); // 'US'
print($record->country->name . "\n"); // 'United States'
print($record->country->names['zh-CN'] . "\n"); // '美国'
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
print($record->city->name . "\n"); // 'Minneapolis'
print($record->postal->code . "\n"); // '55455'
print($record->location->latitude . "\n"); // 44.9733
print($record->location->longitude . "\n"); // -93.2323
It does... I shortly after my last comment I realized that phar wasn't enabled for some reason. Once enabled it was working great!
Good to hear!
Hi,
I have not been able to install "vendor autoload" and I don't want to because when I will transfer my website onto a hosted 1&1 platform, I will not have composer or php available for GeoIp2 installation. I am also developping under Windows.
Therefore, I tried to use require_once with each library contained inside the src/GeoIp2/
require_once 'GeoIp2/ProviderInterface.php'; require_once 'GeoIp2/JsonSerializable.php';
require_once 'GeoIp2/Exception/GeoIp2Exception.php'; require_once 'GeoIp2/Exception/HttpException.php'; require_once 'GeoIp2/Exception/AddressNotFoundException.php'; require_once 'GeoIp2/Exception/InvalidRequestException.php';
require_once 'GeoIp2/Model/Country.php'; require_once 'GeoIp2/Model/City.php'; require_once 'GeoIp2/Model/CityIspOrg.php'; require_once 'GeoIp2/Model/Omni.php';
require_once 'GeoIp2/Database/Reader.php';
use GeoIp2\Database\Reader;
function GetGeoIp2Array(){ $reader = new Reader('GeoIP2-City.mmdb'); $record = $reader->city($_SERVER['REMOTE_ADDR']); $reader->close();
$localisation_array = array( "Country" => (string)$record->country->name, "CountryCode" => (string)$record->country->isoCode, "ContinentCode" => (string)$record->continent->code, "RegionCode" => (string)$record->mostSpecificSubdivision->isoCode, "Region" => (string)$record->mostSpecificSubdivision->name, "Latitude" => (string)$record->location->latitude, "Longitude" => (string)$record->location->longitude, "MetroCode" => (string)$record->mostSpecificSubdivision->isoCode, "ZipCode" => (string)$record->postal->code, "City" => $record->city->name, ); return $localisation_array; }
And I still get this error when executing : Fatal error: Class 'MaxMind\Db\Reader' not found in my_web_folder\geolocalisation\GeoIp2\Database\Reader.php on line 56
If I replace the use directive by the one suggested in the error above, I get this error : Fatal error: Class 'MaxMind\Db\Reader' not found in my_web_folder\geolocalisation\geolocalisation_by_city.php on line 44
Could you please help me :
Thanks very much.