2

i want to show the german name of the users city. Is it possible with the free Version of Maxmind Geoip? I did not find a way to open the GeoLite2-City.mmdb or GeoLiteCity.dat, to see which cities are listed, for building my own translation service. How can i open them?

Moritz
  • 334
  • 5
  • 17

3 Answers3

9

Here's how to do it without Composer.

Change:

require_once '../vendor/autoload.php';
use MaxMind\Db\Reader;
$reader = new Reader('GeoIP2-City.mmdb');

To:

require_once __DIR__ . '/' . 'Db/Reader.php';
require_once __DIR__ . '/' . 'Db/Reader/Decoder.php';
require_once __DIR__ . '/' . 'Db/Reader/InvalidDatabaseException.php';
require_once __DIR__ . '/' . 'Db/Reader/Metadata.php';
require_once __DIR__ . '/' . 'Db/Reader/Util.php';     // new 2014/09
use MaxMind\Db\Reader;
$mmdb= true ? 'GeoLite2-City.mmdb' : 'GeoLite2-Country.mmdb';
$reader = new Reader( __DIR__  . '/' . $mmdb );

You'll need PHP 5.3+. You even get some savings in code and number of files vs. using Composer. (Some testing code is eliminated, as well as the whole Guzzle structure.) Also, it makes it clearer how namespaces work in PHP as a nice replacement for classes (when classes are used just for name-spacing).

The rest of benchmark.php you can discard and start using $reader->get().

If you do want to benchmark, on most platforms you need to modify the rand() call. Try this:

Change:

$ip = long2ip(rand(0, pow(2, 32) -1));

To:

$n= (float)mt_rand(0, pow(2, 31) - 1);
if (mt_rand(0,1)) $n+= pow(2, 31);
$ip = long2ip($n);

Or just join four mt_rand(0,255)'s with '.', which is probably easier!

........................ Edit 2014/09 ........................

Added 'Db/Reader/Util.php' above.

Version of MaxMind-DB-Reader-php: 1.0.0 (2014-09-22)

Your file structure should look like this:

./benchmark.php
./GeoLite2-City.mmdb
./GeoLite2-Country.mmdb
./Db/Reader.php
./Db/Reader/Decoder.php
./Db/Reader/InvalidDatabaseException.php
./Db/Reader/Metadata.php
./Db/Reader/Util.php
kitchin
  • 774
  • 6
  • 9
  • Kitchin, was excited to find your post with directions on how to make use of GeoLite2 without composer. I have my folder structure setup as you instructed, and also updated the code in benchmark.php to be exactly as you stated...but when I run the script nothing shows on screen and my server error-log file says: PHP Fatal error: Class 'MaxMind\Db\Reader\Util' not found in /SERVERPATH/foo/Db/Reader.php on line 238 (*where SERVERPATH is the the full path to server root). Any idea as to why this isn't working for me? Any help would be VERY much appreciated! Thanks! – Mark Sep 01 '14 at 19:59
  • 1
    Awesome, thanks Kitchin that fixed my error. One more (dumb) question tho... how do I actually get it to return a country based on IP? After the $reader = new Reader... line I have $place = $reader->country('##.###.##.###'); (where the #'s are actual IP address numbers) and it's not working. I tried replacing 'country' with 'city' and that didn't work either... I'm sure its something simple, I'm just not sure what parameters I need to be using to get the country returned. Thanks! – Mark Oct 01 '14 at 01:34
  • (and just to follow up on my last comment, the error that is shown in the error log is 'PHP Fatal error: Call to undefined method MaxMind\Db\Reader::city() in <<>>) – Mark Oct 01 '14 at 01:49
  • 1
    @Mark `$t = $reader->get($ip); $country = $t['country']['iso_code'];`. To see all the stuff get() returns, `print_r($t)`. For example, `$t['country']['names']['en']` and `$t['city']['names']['en']`. – kitchin Oct 14 '14 at 09:38
3

The GeoIP Legacy database does not include localized names, but the GeoIP2 (or GeoLite2) database does. You may access the localized name as follows:

<?php
require_once 'vendor/autoload.php';
use GeoIp2\Database\Reader;

$reader = new Reader('/usr/local/share/GeoIP/GeoLite2-City.mmdb');

$record = $reader->city('128.101.101.101');

print($record->country->names['de'] . "\n");

Alternatively, if you would like the reader to default to German and fall back to English when it isn't available, you can set the language in the constructor:

<?php
require_once 'vendor/autoload.php';
use GeoIp2\Database\Reader;

$reader = new Reader('/usr/local/share/GeoIP/GeoLite2-City.mmdb', array('de', 'en'));

$record = $reader->city('128.101.101.101');

print($record->country->name . "\n");
Greg Oschwald
  • 1,716
  • 2
  • 11
  • 14
  • The constructor doesnt accept the fallback array, but it works. Do you have an example without composer? – Moritz Jan 21 '14 at 09:30
  • The second example works for me with the latest version from Composer. There was an unclosed quote that I fixed. – Greg Oschwald Jan 21 '14 at 14:05
  • As far as an example without Composer, although it is possible, you are probably best off using some PSR-0 autoloader. You would also need to install the MaxMind DB API. – Greg Oschwald Jan 21 '14 at 14:06
0

I would recommend using the PHP Extension API if you are concerned at all about performance. You can get upwards of 7 million queries per second with the PHP (C API) extension.

I describe how to compile the extension, and how to use the mmdb databases in PHP to get the localized city name here:

Intro to Maxmind GeoLite2 with Kohana PHP

Geolocate IP Address

Jamie
  • 811
  • 9
  • 13