Git Product home page Git Product logo

geoip2-php's Introduction

GeoIP2 PHP API

Description

This package provides an API for the GeoIP2 and GeoLite2 web services and databases.

Install via Composer

We recommend installing this package with Composer.

Download Composer

To download Composer, run in the root directory of your project:

curl -sS https://getcomposer.org/installer | php

You should now have the file composer.phar in your project directory.

Install Dependencies

Run in your project root:

php composer.phar require geoip2/geoip2:~2.0

You should now have the files composer.json and composer.lock as well as the directory vendor in your project directory. If you use a version control system, composer.json should be added to it.

Require Autoloader

After installing the dependencies, you need to require the Composer autoloader from your code:

require 'vendor/autoload.php';

Install via Phar

Although we strongly recommend using Composer, we also provide a phar archive containing most of the dependencies for GeoIP2. Our latest phar archive is available on our releases page.

Install Dependencies

In order to use the phar archive, you must have the PHP Phar extension installed and enabled.

If you will be making web service requests, you must have the PHP cURL extension installed to use this archive. For Debian based distributions, this can typically be found in the the php-curl package. For other operating systems, please consult the relevant documentation. After installing the extension you may need to restart your web server.

If you are missing this extension, you will see errors like the following:

PHP Fatal error:  Uncaught Error: Call to undefined function MaxMind\WebService\curl_version()

Require Package

To use the archive, just require it from your script:

require 'geoip2.phar';

Optional C Extension

The MaxMind DB API includes an optional C extension that you may install to dramatically increase the performance of lookups in GeoIP2 or GeoLite2 databases. To install, please follow the instructions included with that API.

The extension has no effect on web-service lookups.

IP Geolocation Usage

IP geolocation is inherently imprecise. Locations are often near the center of the population. Any location provided by a GeoIP2 database or web service should not be used to identify a particular address or household.

Database Reader

Usage

To use this API, you must create a new \GeoIp2\Database\Reader object with the path to the database file as the first argument to the constructor. You may then call the method corresponding to the database you are using.

If the lookup succeeds, the method call will return a model class for the record in the database. This model in turn contains multiple container classes for the different parts of the data such as the city in which the IP address is located.

If the record is not found, a \GeoIp2\Exception\AddressNotFoundException is thrown. If the database is invalid or corrupt, a \MaxMind\Db\InvalidDatabaseException will be thrown.

See the API documentation for more details.

City Example

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

// This creates the Reader object, which should be reused across
// lookups.
$cityDbReader = new Reader('/usr/local/share/GeoIP/GeoIP2-City.mmdb');

// Replace "city" with the appropriate method for your database, e.g.,
// "country".
$record = $cityDbReader->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

print($record->traits->network . "\n"); // '128.101.101.101/32'

Anonymous IP Example

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

// This creates the Reader object, which should be reused across
// lookups.
$anonymousDbReader = new Reader('/usr/local/share/GeoIP/GeoIP2-Anonymous-IP.mmdb');

$record = $anonymousDbReader->anonymousIp('128.101.101.101');

if ($record->isAnonymous) { print "anon\n"; }
print($record->ipAddress . "\n"); // '128.101.101.101'
print($record->network . "\n"); // '128.101.101.101/32'

Connection-Type Example

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

// This creates the Reader object, which should be reused across
// lookups.
$connectionTypeDbReader = new Reader('/usr/local/share/GeoIP/GeoIP2-Connection-Type.mmdb');

$record = $connectionTypeDbReader->connectionType('128.101.101.101');

print($record->connectionType . "\n"); // 'Corporate'
print($record->ipAddress . "\n"); // '128.101.101.101'
print($record->network . "\n"); // '128.101.101.101/32'

Domain Example

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

// This creates the Reader object, which should be reused across
// lookups.
$domainDbReader = new Reader('/usr/local/share/GeoIP/GeoIP2-Domain.mmdb');

$record = $domainDbReader->domain('128.101.101.101');

print($record->domain . "\n"); // 'umn.edu'
print($record->ipAddress . "\n"); // '128.101.101.101'
print($record->network . "\n"); // '128.101.101.101/32'

Enterprise Example

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

// This creates the Reader object, which should be reused across
// lookups.
$enterpriseDbReader = new Reader('/usr/local/share/GeoIP/GeoIP2-Enterprise.mmdb');

// Use the ->enterprise method to do a lookup in the Enterprise database
$record = $enterpriseDbReader->enterprise('128.101.101.101');

print($record->country->confidence . "\n"); // 99
print($record->country->isoCode . "\n"); // 'US'
print($record->country->name . "\n"); // 'United States'
print($record->country->names['zh-CN'] . "\n"); // '美国'

print($record->mostSpecificSubdivision->confidence . "\n"); // 77
print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'

print($record->city->confidence . "\n"); // 60
print($record->city->name . "\n"); // 'Minneapolis'

print($record->postal->code . "\n"); // '55455'

print($record->location->accuracyRadius . "\n"); // 50
print($record->location->latitude . "\n"); // 44.9733
print($record->location->longitude . "\n"); // -93.2323

print($record->traits->network . "\n"); // '128.101.101.101/32'

ISP Example

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

// This creates the Reader object, which should be reused across
// lookups.
$ispDbReader = new Reader('/usr/local/share/GeoIP/GeoIP2-ISP.mmdb');

$record = $ispDbReader->isp('128.101.101.101');

print($record->autonomousSystemNumber . "\n"); // 217
print($record->autonomousSystemOrganization . "\n"); // 'University of Minnesota'
print($record->isp . "\n"); // 'University of Minnesota'
print($record->organization . "\n"); // 'University of Minnesota'

print($record->ipAddress . "\n"); // '128.101.101.101'
print($record->network . "\n"); // '128.101.101.101/32'

Database Updates

You can keep your databases up to date with our GeoIP Update program. Learn more about GeoIP Update on our developer portal.

Web Service Client

Usage

To use this API, you must create a new \GeoIp2\WebService\Client object with your $accountId and $licenseKey:

$client = new Client(42, 'abcdef123456');

You may also call the constructor with additional arguments. The third argument specifies the language preferences when using the ->name method on the model classes that this client creates. The fourth argument is additional options such as host and timeout.

For instance, to call the GeoLite2 web service instead of the GeoIP2 web service:

$client = new Client(42, 'abcdef123456', ['en'], ['host' => 'geolite.info']);

To call the Sandbox GeoIP2 web service instead of the production GeoIP2 web service:

$client = new Client(42, 'abcdef123456', ['en'], ['host' => 'sandbox.maxmind.com']);

After creating the client, you may now call the method corresponding to a specific endpoint with the IP address to look up, e.g.:

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

If the request succeeds, the method call will return a model class for the endpoint you called. This model in turn contains multiple record classes, each of which represents part of the data returned by the web service.

If there is an error, a structured exception is thrown.

See the API documentation for more details.

Example

<?php
require_once 'vendor/autoload.php';
use GeoIp2\WebService\Client;

// This creates a Client object that can be reused across requests.
// Replace "42" with your account ID and "license_key" with your license
// key. Set the "host" to "geolite.info" in the fourth argument options
// array to use the GeoLite2 web service instead of the GeoIP2 web
// service. Set the "host" to "sandbox.maxmind.com" in the fourth argument
// options array to use the Sandbox GeoIP2 web service instead of the
// production GeoIP2 web service.
$client = new Client(42, 'abcdef123456');

// Replace "city" with the method corresponding to the web service that
// you are using, e.g., "country", "insights".
$record = $client->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

print($record->traits->network . "\n"); // '128.101.101.101/32'

Values to use for Database or Array Keys

We strongly discourage you from using a value from any names property as a key in a database or array.

These names may change between releases. Instead we recommend using one of the following:

  • GeoIp2\Record\City - $city->geonameId
  • GeoIp2\Record\Continent - $continent->code or $continent->geonameId
  • GeoIp2\Record\Country and GeoIp2\Record\RepresentedCountry - $country->isoCode or $country->geonameId
  • GeoIp2\Record\Subdivision - $subdivision->isoCode or $subdivision->geonameId

What data is returned?

While many of the end points return the same basic records, the attributes which can be populated vary between end points. In addition, while an end point may offer a particular piece of data, MaxMind does not always have every piece of data for any given IP address.

Because of these factors, it is possible for any end point to return a record where some or all of the attributes are unpopulated.

See the GeoIP2 web service docs for details on what data each end point may return.

The only piece of data which is always returned is the ipAddress attribute in the GeoIp2\Record\Traits record.

Integration with GeoNames

GeoNames offers web services and downloadable databases with data on geographical features around the world, including populated places. They offer both free and paid premium data. Each feature is unique identified by a geonameId, which is an integer.

Many of the records returned by the GeoIP2 web services and databases include a geonameId property. This is the ID of a geographical feature (city, region, country, etc.) in the GeoNames database.

Some of the data that MaxMind provides is also sourced from GeoNames. We source things like place names, ISO codes, and other similar data from the GeoNames premium data set.

Reporting data problems

If the problem you find is that an IP address is incorrectly mapped, please submit your correction to MaxMind.

If you find some other sort of mistake, like an incorrect spelling, please check the GeoNames site first. Once you've searched for a place and found it on the GeoNames map view, there are a number of links you can use to correct data ("move", "edit", "alternate names", etc.). Once the correction is part of the GeoNames data set, it will be automatically incorporated into future MaxMind releases.

If you are a paying MaxMind customer and you're not sure where to submit a correction, please contact MaxMind support for help.

Other Support

Please report all issues with this code using the GitHub issue tracker.

If you are having an issue with a MaxMind service that is not specific to the client API, please see our support page.

Requirements

This library requires PHP 8.1 or greater.

This library also relies on the MaxMind DB Reader.

Contributing

Patches and pull requests are encouraged. All code should follow the PSR-2 style guidelines. Please include unit tests whenever possible. You may obtain the test data for the maxmind-db folder by running git submodule update --init --recursive or adding --recursive to your initial clone, or from https://github.com/maxmind/MaxMind-DB

Versioning

The GeoIP2 PHP API uses Semantic Versioning.

Copyright and License

This software is Copyright (c) 2013-2023 by MaxMind, Inc.

This is free software, licensed under the Apache License, Version 2.0.

geoip2-php's People

Contributors

2shortplanks avatar andyjack avatar autarch avatar benmorel avatar borisz avatar christophermluna avatar dependabot-preview[bot] avatar dependabot[bot] avatar dlieou avatar faktas2 avatar horgh avatar kevcenteno avatar klp2 avatar mlocati avatar najiobeid avatar oalders avatar oschwald avatar patrickcronin avatar peter279k avatar ph-7 avatar rafl avatar ravage84 avatar reedy avatar seldaek avatar sgiehl avatar shadromani avatar ugexe avatar wesrice avatar zyphlar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

geoip2-php's Issues

Remove Guzzle dependency

Please remove the Guzzle library as a dependency.

Having Guzzle as a dependency clashes with the projects already using an another version of Guzzle.

It can be added as a recommendation for people who want to use the web services.

Autoload unavailable

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 :

  • have the right "require" order
  • have the right "use" namespaces in order to make it work without installing composer.

Thanks very much.

Can't catch GeoIp2\Exception\AddressNotFoundException

Hi guys,

I've been trying by infinite ways to catch this exception.

The exception comes from https://github.com/maxmind/GeoIP2-php/blob/master/src/GeoIp2/Database/Reader.php#L167

This is not catching the exception:

use GeoIp2\Database\Reader;
...
...
try {
    $reader = new Reader(app_path().'/database/maxmind/GeoLite2-City.mmdb');
    $record = $reader->city($ip); // $ip defined before, trying with 234.234.34.4
    print($record->country->isoCode . "\n");

    } catch (Exception $e) {
        echo 'Caught!';
    }
}
...

I've tried a lot of things, but anything works.... :(
However, this simple try codeblock I pasted above should work, right?

Am I doing anything wrong? How can I catch that exception?

Encoding of city names

Hi. I was wondering what is the encoding of the city names. I'm trying to insert a city name in a MongoDB database, but I get an exception:non-utf8 string, so I guess it is not utf-8?

not able to access mostSpecificSubdivision values

if(isset($record->mostSpecificSubdivision) && !empty($record->mostSpecificSubdivision->names) )) {
....
}

when I do var_dump($record->mostSpecificSubdivision) then I am getting an object displayed but when I check for this property using empty() and isset() then I am getting false response.

Mismatch between documentation and code

Properties $name and $names not used in class 'RepresentedCountry', but specified in documentation

$record->representedCountry->name;
--> thrown an exception

$record->representedCountry->namespace;
--> works!

Missing country property, three letter country code

Currently in the middle of upgrading away from the legacy geoip extension to this package and have run into an issue. In the past I could use geoip_country_code3_by_name to get the three letter country code for an IP address. Unless I am missing something, I cannot see a way to get that with these new API's.

Unfortunately we require the use of the three letter country code, so just the two letter country code won't work.

No docs for available object in database!

I've downloaded the country database but didn't found anything which will guide me about the data structure in database :(
I tried ```php
...
$record=$reader->country("118.90.116.80");
echo $record->isoCode;

and it thrown error!
Please help

Unexpected behaviour with Isset() and empty()

Hello,

I'm seeing a strange behaviour with isset() and empty(), both returning invalid results for valid data.

$ipAddress = '128.101.101.200';

$reader = new \GeoIp2\Database\Reader('/usr/share/GeoIP/GeoLite2-Country.mmdb');
$countryRecord = $reader->country($ipAddress);

echo $countryRecord->country->name , "\n"; // United States
$isset = isset($countryRecord->country->name);
var_dump($isset); // bool(false) ?
$empty = empty($countryRecord->country->name);
var_dump($empty); // bool(true) ?
$empty = ($countryRecord->country->name == '');
var_dump($empty); // bool(false)
echo "\n";

$reader = new \GeoIp2\Database\Reader('/usr/share/GeoIP/GeoLite2-City.mmdb');
$cityRecord = $reader->city($ipAddress);

echo $cityRecord->country->name , "\n"; // United States
$isset = isset($cityRecord->country->name);
var_dump($isset); // bool(false) ?
$empty = empty($cityRecord->country->name);
var_dump($empty); // bool(true) ?
$empty = ($cityRecord->country->name == '');
var_dump($empty); // bool(false)
echo "\n";

Get ISP

Hello,

How can I get ISP?

Documentation update - PHAR requirements and common issues

Hello,
I had some issues trying to implement the PHAR on my production server. I finally managed to fix it by reading the PHPUnit documentation about phar implementation and requirements

image

Could you please update your documentation to include more details about this?
Thanks

C Extension - optimalization questions

Hi,

I installed C extension, so in phpinfo() I see

maxminddb
Version 1.0.3

I am using also composer and geoip2/geoip2 (v2.3.3).

I am wondering, if C extension is actually used. When I uninstall PHP lib, it throws error. The thing is I need really optimise my IP lookups, do you have any suggestions ? Now I see it is really slow (slowest part of my website - sometimes it takes 5(!) seconds for 1 lookup, here is screenshot:

https://www.dropbox.com/s/r9r4pi0qqmg1koq/Screenshot%202015-11-24%2001.30.16.png?dl=0

I have on my servers YAC, Redis etc, so maybe freezing object into memory is possible ? I dont want to cache IP -> country into redis...

Unable to get user_type and queries_remaining

Hi,
I have just started to use the GeoIp PHP/composer class, and have noticed the following

$clean_ip="IP ADDRESS";
use GeoIp2\WebService\Client;
$client=new Client(ID, 'KEY');
$record=$client->omni($clean_ip);
$org=$records->traits->organization;
$user_type=$record->traits->user_type;
$remaining=$records->maxmind->queries_remaining;

the $org works, but i get an 'Unknown attribute: user_type' and 'Unknown attribute: queries_remaining' for the user_type and remaining queries.
Is this just my bad coding/understanding or is it a bug?

thanks

Matt

Replace Guzzle with actual version: 4

Now when installing over composer it requires old (3) version of Guzzle which itself requires part of Symfony library (that does't used by GeoIP2)

mostSpecificSubdivision not set when using Twig

Following the City Example in README.md, I've found that the mostSpecificSubdivision (region) is found, but is NULL when used inside Twig templates:

print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'

var_dump($record->mostSpecificSubdivision);

You can find 'Minnesota' all over the dumped $recordobject, but not the name or isoCode properties.

{{ record.mostSpecificSubdivision.isoCode }} // ...
{{ record.mostSpecificSubdivision.isoCode ?: 'N/A' }} // 'N/A'
{{ dump(record.mostSpecificSubdivision) }} // NULL

The data is there, just not accessible for some reason.

GeoIp2 and legacy format

In legacy format we had $location->region attribute, is this attribute represented in new GeoIp2 client? If compared to mostSpecificSubdivision i would not say it is the same, because identities (id) are not the same as for legacy.

I need city

HelloI need find city for ip, I install maxmind/GeoIP2-php and download file GeoLite2-City.mmdb 31mb GeoLite2-City.mmdb 2,2mb and create service AdditionalFunction and function getInfoIpCity, getInfoIpCountry and when developer registration I use this function like this:

 $ip = $request->getClientIp();
 $record = $hAid->getInfoIpCountry($ip);
 $get_record = $hAid->getInfoIpCity($ip);
 $record_coutry = $record->country->name;

and service:

class AdditionalFunction
{
private $rootDir;

public function setRootDir($rootDir)
{
$this->rootDir = $rootDir;
}

public function getInfoIpCountry($ip)
{
 try {
   $reader = new Reader($this->rootDir.'/data/GeoLite2-Country.mmdb');
   $data = $reader->country($ip);
 } catch (\Exception $e) {
    $data = null;
 }

 return $data;
 }

 public function getInfoIpCity($ip)
{
 try {
   $reader = new Reader($this->rootDir.'/data/GeoLite2-City.mmdb');
   $data = $reader->city($ip);
    $m = $data->country->name;
    $t = $data->country->isoCode;
    $b = $data->mostSpecificSubdivision->name;
    $c = $data->city->name;
 } catch (\Exception $e) {
     $data = null;
 }

 return $data;
 }
 }

coutry find right but in dump I have $c = null, $b = null why???? I need city

Add a dependencies list to your documentation

It would be really awesome if there were a dependencies list included in the documentation for this library... Calling out mbstring specifically would be sweet...

Any chance of adding one?

Possible to get Timezone from country code ?

Hello,

I have a country code and I need to get its timezone.

Most of the time, the country code comes from GeoIP and I can just use $reader->country($ip)->location->timeZone.

However sometimes the country code comes from the URL, using GeoIP1 I could get the timezone using get_time_zone() from timezone.php.

I've looked carefully through the docs and it seems like the only entry point is the IP now, having a country code does not allow me to lookup what I need to.

Did I miss something ?

Create Phar files with documentation intact

The current phar file has zero documentation within it.

This means ID's get very confused when you are trying to use the models as either it cannot find what you are asking for, or thinks your accessing a private method.

If the phar file shipped with it's PHPdoc still present, this issue would be resolved.

screen shot 2015-09-08 at 14 47 55

Enriching returned record data

Hi,

I am the developer of a wordpress plugin that provides easy access to your API (https://wordpress.org/plugins/geoip-detect/) and would like to add new properties to the returned object. The only way I could do it is a) a proxy object or b) modifying the protected variable $raw or $validAttributes. Is there a nicer way to do this?

For example, I would propose a new top-level property that contains either a raw stdclass (approx. what the legacy API did) or a class that has a static function "addValidAttribute" allowing 3rd-party-library to register their property names. The Name of the proposed property could be used to communicate that this is non-standard Maxmind API.

Happy to send a pull request if you like me to.

Discrepency in API regarding Insights get information

Looking at pulling the some data down and while some work, some do not.

Example:
$record->subdivisions->names
$record->subdivisions->names->en
$record->subdivisions->names[en]

Returns "" (nothing). No errors in the log.

If I pull the "subdivisions" array and convert the set to JSON, I get this back:

echo json_encode($record->subdivisions, JSON_UNESCAPED_UNICODE);
returns:
[{"confidence":60,"iso_code":"BY","geoname_id":2951839,"names":{"ru":"Бавария","zh-CN":"巴伐利亚","de":"Bayern","en":"Bavaria","es":"Baviera","fr":"Bavière","ja":"バイエルン州","pt-BR":"Baviera"}}]

Looking at the traits php file, I see that the "types" exist in the file, yet when I make the calls, I get nothing back. So I know the data is there but I am unable to retrieve it via the API code correctly when "names" is referenced.

Also looking into the php file and the reported output, there is a discrepancy in the naming versus the Dev maxmind site.

ie Subdivisions (which is subdivision.php and subdivision namespace).
http://dev.maxmind.com/geoip/geoip2/web-services/#subdivisions
object names such as userType when its referred on the web as user_type

This is a trivial matter but it makes referencing the maxmind page a bit troublesome as what you read there may not be how you access it in code. This also causes a bit of problem when the array you retrieve specifically returns "user_type" but to make the call to it you must use userType.

ie
$record->traits->userType

if printing out record->traits:
{"user_type":"hosting","autonomous_system_number":24940,"autonomous_system_organization":"Hetzner Online GmbH","domain":"your-server.de","isp":"Hetzner Online GmbH","organization":"Hetzner Online AG","ip_address":"78.46.100.73"}

Timezone ID invalid

One single visitor create this php error report:

date_default_timezone_set(): Timezone ID 'Asia/Tokyo, session_database=1ee2a5f346389b7f02332231e08def84384d5411~54fb28e5cf93a2-08272203' is invalid

The timezone string from geoip_time_zone_by_country_and_region() included the session id separated with a comma ","? How can this happen? Is this a bug in php (5.5.22)?

should be created by this code (short version)

    $result = geoip_record_by_name('180.144.227.111');
    if ($result)
    {           date_default_timezone_set(geoip_time_zone_by_country_and_region($result['country_code'],$result['region']));
    }

I have tested with original code and its working fine for this IP.

Documentation on the structure returned by Reader()

I'm using this implementation in Symfony2 project and so far so good. Although I would like to get "City", "State", "Country" from an IP address.

I did a test with my IP address and I was able to get the "City" and the "Country" using the following two objects:

$record->city->names['en']
$record->country->names['en']

I haven't figure out how to get the "State" though, I'll be more than glad if you can point me to the documentation (if it exists) on how to get the city name.

Regards

Slow lookups

Hi there

I've been comparing this library to the legacy geoip-api-php (https://github.com/maxmind/geoip-api-php) in terms of lookup speed.
I've read that the new format (.mmdb) is supposed to offer faster lookups than the old format (.dat), however my tests show the opposite, with way slower lookups.

Consider the below code:

use GeoIp2\Database\Reader;

function ip_lookup_geoip($ip) {
  $geoip_old_reader = geoip_open(realpath('.').'/sites/all/libraries/GeoLiteCity.dat', GEOIP_STANDARD);
  $record = geoip_record_by_addr($geoip_old_reader, $ip);
  geoip_close($geoip_old_reader);
  return $record;
}

function ip_lookup_geoip2($ip) {
  $geoip_reader = new Reader(realpath('.').'/sites/all/libraries/GeoLite2-City.mmdb');

  try {
    $record = $geoip_reader->city($ip);
    return $record;
  } catch (Exception $e) {
    print('An error happened while looking up IP !ip: '.$e->getMessage());
  }

  return FALSE;
}

$ip = '173.194.115.23';

$start = microtime(TRUE);
$record = ip_lookup_geoip($ip);
$elapsed = microtime(TRUE) - $start;
print("[geoip] Lookup time: $elapsed\r\n");
print("[geoip] $ip: {$record->country_name} > {$record->city}\r\n");

$start = microtime(TRUE);
$record = ip_lookup_geoip2($ip);
$elapsed = microtime(TRUE) - $start;
print("[geoip2] Lookup time: $elapsed\r\n");
print("[geoip2] $ip: {$record->country->name} > {$record->city->name}\r\n");

Execution trace:

[geoip] Lookup time: 0.0038161277770996
[geoip] 173.194.115.23: United States > Mountain View
[geoip2] Lookup time: 0.14523100852966
[geoip2] 173.194.115.23: United States > Mountain View

Am I missing something here?

Ubuntu 16.04 PHP 7

Composer install does not work.

ler@Geoip-Dev-Web:/var/www/uploads$ php composer.phar require geoip2/geoip2:~2.0
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

Problem 1
- The requested package geoip2/geoip2 No version set (parsed as 1.0.0) is satisfiable by geoip2/geoip2[No version set (parsed as 1.0.0)] but these conflict with your requirements or minimum-stability.

Installation failed, reverting ./composer.json to its original content.

Caching options

Hello,

Thanks for this awesome library.
I'd like to see more caching options to accelerate lookup speed like caching the database file into memory using shmop PHP extension.

Thanks

GeoIP2-php requires a deprecated dependency

GeoIP2 package uses a deprecated library. Installation via composer shows the following message:

guzzle/guzzle suggests installing guzzlehttp/guzzle (Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated.)

Calling Reader::country() returns null with City database

I'm working on a project where we are required to geolocate visitors' country and, in some cases, visitors' city as well. Due to that, I switcher from the Country database to the City one, but I encountered an unexpected behaviour, described below:

$reader = new Reader('GeoLite2-Country.mmdb');
$country = $reader->country('87.65.122.63')->isoCode; // This returns "BE - Belgium"

$reader = new Reader('GeoLite2-City.mmdb');
$country = $reader->country('87.65.122.63')->isoCode; // This returns false

Questions

  1. Is such behaviour correct? I thought that the City database could be used for both Country and City detection.
  2. Our target is to always detect the country and, if possible, the city. If the City database can only be used for city detection, what happens if such information cannot be determined? For example, if I pass an IP Address and the city cannot be determined, how do I get the country from it?

Web service behind proxy

Is there a way to make the script connect to Maxmind service through a proxy? My webserver can't make direct connections.

Error when use GeoIP2-Country.mmdb

Hi,

When I use GeoIP2-Country.mmdb instead of GeoIP2-City.mmdb on
$reader = new Reader('/usr/local/share/GeoIP/GeoIP2-Country.mmdb');

I got an error!! How can I use GeoIP2-Country.mmdb ?

Thanks

SSL: certificate verification failed on OS X 10.11.6

Getting an exception:

'MaxMind\Exception\HttpException' with message 'cURL error (51): SSL: certificate verification failed (result: 5)'

This only happens locally on OS X El Capitan (10.11.6) and It might have to do with the SSL version used by php and/or curl (SecureTransport instead of OpenSSL).

php -i | grep "SSL Version"
SSL Version => SecureTransport

While looking for a workaround, I tried specifying another cacert.pem in new Client() and it worked out. The cacert.pem used was the one provided by composer residing in ~/.composer/cacert.pem

Toolbar management and site issue when goes from 2.3.1 to 2.3.2

Message:

Case mismatch between loaded and declared class names: GeoIp2\Compat\JsonSerializable vs GeoIp2\Compat\JSONSerializable

Trace:

[1] RuntimeException: Case mismatch between loaded and declared class names: GeoIp2\Compat\JsonSerializable vs GeoIp2\Compat\JSONSerializable
    at n/a
        in /path/to/project/vendor/symfony/symfony/src/Symfony/Component/Debug/DebugClassLoader.php line 177

    at Symfony\Component\Debug\DebugClassLoader->loadClass('GeoIp2\Compat\JsonSerializable')
        in  line 

    at spl_autoload_call('GeoIp2\Compat\JsonSerializable')
        in /path/to/project/vendor/geoip2/geoip2/src/Model/AbstractModel.php line 11

    at require('/path/to/project/vendor/geoip2/geoip2/src/Model/AbstractModel.php')
        in /path/to/project/vendor/symfony/symfony/src/Symfony/Component/Debug/DebugClassLoader.php line 152

    at Symfony\Component\Debug\DebugClassLoader->loadClass('GeoIp2\Model\AbstractModel')
        in  line 

    at spl_autoload_call('GeoIp2\Model\AbstractModel')
        in /path/to/project/vendor/geoip2/geoip2/src/Model/Country.php line 36

    at require('/path/to/project/vendor/geoip2/geoip2/src/Model/Country.php')
        in /path/to/project/vendor/symfony/symfony/src/Symfony/Component/Debug/DebugClassLoader.php line 152

    at Symfony\Component\Debug\DebugClassLoader->loadClass('GeoIp2\Model\Country')
        in  line 

    at spl_autoload_call('GeoIp2\Model\Country')
        in /path/to/project/vendor/geoip2/geoip2/src/Model/City.php line 58

    at require('/path/to/project/vendor/geoip2/geoip2/src/Model/City.php')
        in /path/to/project/vendor/symfony/symfony/src/Symfony/Component/Debug/DebugClassLoader.php line 152

    at Symfony\Component\Debug\DebugClassLoader->loadClass('GeoIp2\Model\City')
        in  line 

    at spl_autoload_call('GeoIp2\Model\City')
        in /path/to/project/vendor/geoip2/geoip2/src/Database/Reader.php line 181

    at GeoIp2\Database\Reader->modelFor('City', 'City', '195.101.111.115')
        in /path/to/project/vendor/geoip2/geoip2/src/Database/Reader.php line 70

    at GeoIp2\Database\Reader->city('195.101.111.115')
        in /path/to/project/src/Acme/Bundle/ServiceBundle/Service/GeoipService.php line 46

    at Ikuw\Bundle\ServiceBundle\Service\GeoipService->geocode(object(Request))
        in /path/to/project/src/Acme/Bundle/ServiceBundle/EventListener/TimezoneListener.php line 52

    at Ikuw\Bundle\ServiceBundle\EventListener\TimezoneListener->onKernelRequest(object(GetResponseEvent), 'kernel.request', object(TraceableEventDispatcher))
        in  line 

    at call_user_func(array(object(TimezoneListener), 'onKernelRequest'), object(GetResponseEvent), 'kernel.request', object(TraceableEventDispatcher))
        in /path/to/project/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php line 61

    at Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(object(GetResponseEvent), 'kernel.request', object(ContainerAwareEventDispatcher))
        in  line 

    at call_user_func(object(WrappedListener), object(GetResponseEvent), 'kernel.request', object(ContainerAwareEventDispatcher))
        in /path/to/project/app/cache/dev/classes.php line 1791

    at Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(array(object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener)), 'kernel.request', object(GetResponseEvent))
        in /path/to/project/app/cache/dev/classes.php line 1724

    at Symfony\Component\EventDispatcher\EventDispatcher->dispatch('kernel.request', object(GetResponseEvent))
        in /path/to/project/app/cache/dev/classes.php line 1885

    at Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.request', object(GetResponseEvent))
        in /path/to/project/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php line 124

    at Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch('kernel.request', object(GetResponseEvent))
        in /path/to/project/app/bootstrap.php.cache line 3043

    at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), '1')
        in /path/to/project/app/bootstrap.php.cache line 3016

    at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), '1', true)
        in /path/to/project/app/bootstrap.php.cache line 3165

    at Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel->handle(object(Request), '1', true)
        in /path/to/project/app/bootstrap.php.cache line 2406

    at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
        in /path/to/project/web/app_dev.php line 29

PSR-4 settings on composer.json causes geoip2 to override all autoloading

The package's composer.json has this for autoload settings:

"autoload": {
    "psr-4": {
        "GeoIp2\\": "src",
        "": "compat/"
    }
}

The fact that "" is set to the compat folder means that all autoloading will look for classes inside that folder before moving on to the correct path. I became aware of this because of numerous "No such file or directory" warnings on our servers, seen by this bit of process trace:

access("/home/project/vendor/geoip2/geoip2/compat/Illuminate/View/View.php", F_OK) = -1 ENOENT (No such file or directory)
access("/home/project/vendor/laravel/framework/src/Illuminate/View/View.php", F_OK) = 0

This goes on and on with all classes.

Am I doing something wrong on my side? I'm not even using geoip2, but it is required in one of my packages, and since composer puts on the autoload_psr4.php array just by being a requirement, this issue is present on all my projects.

I've tested this by putting a random class inside vendor/geoip2/geoip2/compact, i.e. vendor/geoip2/geoip2/compact/Namespace/Class.php, then calling it in my code. Even though another package (the actual "owner" of the class) states that Namespace/Class should be found within vendor/package/src/Namespace/Class, the PHP file inside geoip2 is what gets loaded.

Is there a way around this? Since the compat folder contains only a workaround for supporting 5.3, is it a worthwhile compromise to have this issue?

2.1.0 Phar file issues.

Hi,

I updated my phar file from 2.0.0 to 2.1.0 and it causes 2 issues.

  1. It echos - #!/usr/bin/env php at the top of the file where i require it.
  2. Now because this file already outputs before the other files, it ends up throwing headers already sent warning:
Warning</b>:  session_start(): Cannot send session cookie - headers already sent by (output started at path/to/geoip2.phar:2)

Please fix this ASAP. Thanks!

Getting Warning: Unexpected character in input: '' (ASCII=27) state=0 error on mmdb file

Im getting this error as app reads on the mmdb file:

Warning: Unexpected character in input: '�' (ASCII=27) state=0 in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Warning: Unexpected character in input: ' in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Warning: Unexpected character in input: '�' (ASCII=27) state=0 in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Warning: Unexpected character in input: ' in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Warning: Unexpected character in input: '�' (ASCII=8) state=0 in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Warning: Unexpected character in input: ' in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Warning: Unexpected character in input: ' in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Warning: Unexpected character in input: '�' (ASCII=8) state=0 in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Warning: Unexpected character in input: ' in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Warning: Unexpected character in input: '�' (ASCII=8) state=0 in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Warning: Unexpected character in input: ' in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

Parse error: syntax error, unexpected '>' in /usr/local/ampps/www/coco/public/assets/data/GeoLite2-City.mmdb on line 60

PHP V: 5.6.21
BCMath extension is installed.

Wrong doc comments

This

return $record->city->name

might return null. Same with timeZone. Probably more.

Doc comment for city says:

@Property string $name The name of the city based on the locales list passed to the constructor. This attribute is returned by all end points.

Should be changed to something like:

@Property string|null $name The name of the city based on the locales list passed to the constructor (null in case the city is unknown). This attribute is returned by all end points.

Also I think it's better to remove all cases of This attribute is returned by all end points.
Instead, better only make a note in case the attribute is not supported by all endpoints.

Log files fill up with AddressNotFoundException on private IPv6 addresses

Affects: Torann/laravel-geoip#55

Error: The address ::1 is not in the database.

I haven't seen any from 127.0.0.1 (IPv4), but GeoIP2 fills up logs very quickly with the above error and stack trace when the error is thrown (discovered by rap2hpoutre/laravel-log-viewer) at https://github.com/maxmind/GeoIP2-php/blob/master/src/Database/Reader.php#L220-L224

Consider adding the following (or a similar implementation) to skip database check if the IP is private:

function is_private_IP($ip) {
    return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE |  FILTER_FLAG_NO_RES_RANGE);
}

Source: https://arjunphp.com/check-if-an-ip-address-is-private-with-php/

issue opening city-europe db

We have bought licence for the GeoIP2-City-Europe database.

The code (found on http://maxmind.github.io/GeoIP2-php/) :
$reader = new Reader($path.'\data\GeoIP2-City-Europe_20140909\GeoIP2-City-Europe.mmdb'); $record = $reader->city('128.101.101.101');
throws fatal error :
"Uncaught exception 'BadMethodCallException' with message 'The city method cannot be used to open a GeoIP2-City-Europe database".

Please can you indicate the correct method name to use.
Thx in advance

How do you query the continent?

Hi,

How do I query the continent?

I've tried with

<?php

// https://github.com/maxmind/geoip-api-php
// https://github.com/maxmind/GeoIP2-php
require __DIR__ . '/geoip2.phar';

use GeoIp2\Database\Reader;

$ipAddress = '1.2.3.4';

$reader = new Reader('GeoLite2-Country.mmdb');
$record = $reader->country($ipAddress);

// print($record->continent->isoCode . "\n"); // ???
print_r($record->country->isoCode . "\n"); // works for the country

print_r( $record );

The result object contains it. It would be stupid for me to var_export the variable and search for it in the string.

US
GeoIp2\Model\Country Object
(
    [continent:protected] => GeoIp2\Record\Continent Object
        (
            [validAttributes:protected] => Array
                (
                    [0] => code
                    [1] => geonameId
                    [2] => names
                )

            [locales:GeoIp2\Record\AbstractPlaceRecord:private] => Array
                (
                    [0] => en
                )

            [record:GeoIp2\Record\AbstractRecord:private] => Array
                (
                    [code] => NA
                    [geoname_id] => 6255149
                    [names] => Array
                        (
                            [de] => Nordamerika
                            [en] => North America
                            [es] => Norteamérica
                            [fr] => Amérique du Nord
                            [ja] => 北アメリカ
                            [pt-BR] => América do Norte
                            [ru] => Северная Америка
                            [zh-CN] => 北美洲
                        )

                )

        )

    [country:protected] => GeoIp2\Record\Country Object
        (
            [validAttributes:protected] => Array
                (
                    [0] => confidence
                    [1] => geonameId
                    [2] => isoCode
                    [3] => names
                )

            [locales:GeoIp2\Record\AbstractPlaceRecord:private] => Array
                (
                    [0] => en
                )

            [record:GeoIp2\Record\AbstractRecord:private] => Array
                (
                    [geoname_id] => 6252001
                    [iso_code] => US
                    [names] => Array
                        (
                            [de] => USA
                            [en] => United States
                            [es] => Estados Unidos
                            [fr] => États-Unis
                            [ja] => アメリカ合衆国
                            [pt-BR] => Estados Unidos
                            [ru] => Сша
                            [zh-CN] => 美国
                        )

                )

        )

    [locales:protected] => Array
        (
            [0] => en
        )

    [maxmind:protected] => GeoIp2\Record\MaxMind Object
        (
            [validAttributes:protected] => Array
                (
                    [0] => queriesRemaining
                )

            [record:GeoIp2\Record\AbstractRecord:private] => Array
                (
                )

        )

    [registeredCountry:protected] => GeoIp2\Record\Country Object
        (
            [validAttributes:protected] => Array
                (
                    [0] => confidence
                    [1] => geonameId
                    [2] => isoCode
                    [3] => names
                )

            [locales:GeoIp2\Record\AbstractPlaceRecord:private] => Array
                (
                    [0] => en
                )

            [record:GeoIp2\Record\AbstractRecord:private] => Array
                (
                    [geoname_id] => 6252001
                    [iso_code] => US
                    [names] => Array
                        (
                            [de] => USA
                            [en] => United States
                            [es] => Estados Unidos
                            [fr] => États-Unis
                            [ja] => アメリカ合衆国
                            [pt-BR] => Estados Unidos
                            [ru] => Сша
                            [zh-CN] => 美国
                        )

                )

        )

    [representedCountry:protected] => GeoIp2\Record\RepresentedCountry Object
        (
            [validAttributes:protected] => Array
                (
                    [0] => confidence
                    [1] => geonameId
                    [2] => isoCode
                    [3] => names
                    [4] => type
                )

            [locales:GeoIp2\Record\AbstractPlaceRecord:private] => Array
                (
                    [0] => en
                )

            [record:GeoIp2\Record\AbstractRecord:private] => Array
                (
                )

        )

    [traits:protected] => GeoIp2\Record\Traits Object
        (
            [validAttributes:protected] => Array
                (
                    [0] => autonomousSystemNumber
                    [1] => autonomousSystemOrganization
                    [2] => domain
                    [3] => isAnonymousProxy
                    [4] => isSatelliteProvider
                    [5] => isp
                    [6] => ipAddress
                    [7] => organization
                    [8] => userType
                )

            [record:GeoIp2\Record\AbstractRecord:private] => Array
                (
                    [ip_address] => 1.2.3.4
                )

        )

    [raw:protected] => Array
        (
            [continent] => Array
                (
                    [code] => NA
                    [geoname_id] => 6255149
                    [names] => Array
                        (
                            [de] => Nordamerika
                            [en] => North America
                            [es] => Norteamérica
                            [fr] => Amérique du Nord
                            [ja] => 北アメリカ
                            [pt-BR] => América do Norte
                            [ru] => Северная Америка
                            [zh-CN] => 北美洲
                        )

                )

            [country] => Array
                (
                    [geoname_id] => 6252001
                    [iso_code] => US
                    [names] => Array
                        (
                            [de] => USA
                            [en] => United States
                            [es] => Estados Unidos
                            [fr] => États-Unis
                            [ja] => アメリカ合衆国
                            [pt-BR] => Estados Unidos
                            [ru] => Сша
                            [zh-CN] => 美国
                        )

                )

            [registered_country] => Array
                (
                    [geoname_id] => 6252001
                    [iso_code] => US
                    [names] => Array
                        (
                            [de] => USA
                            [en] => United States
                            [es] => Estados Unidos
                            [fr] => États-Unis
                            [ja] => アメリカ合衆国
                            [pt-BR] => Estados Unidos
                            [ru] => Сша
                            [zh-CN] => 美国
                        )

                )

            [traits] => Array
                (
                    [ip_address] => 1.2.3.4
                )

        )

)

Call to undefined function MaxMind\Db\Reader\bcadd()

Hi, I'm new to this API, so I've tried the example code that is at home page. First I've had to add "symfony/event-dispatcher": "2.4.0" dependency to composer.json because it isn't able to download 2.4.1 version that is what requires guzzle library.

Then I've put the example code into a test, but I've got this error:
Code:
$reader = new Reader(dirname(FILE) . '/../../config/GeoLite2-City.mmdb');

Error:
Call to undefined function MaxMind\Db\Reader\bcadd() in ...vendor/maxmind-db/reader/src/MaxMind/Db/Reader/Decoder.php on line 25

I've seen that there's another closed issue that supposedly solves the problem, but I still got the same error. Besides, I've tried to add a dependecy:

"ext-bcmath":"*"

But composer is not able to find that dependency, any ideas?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.