maxmind / GeoIP2-php

PHP API for GeoIP2 webservice client and database reader
https://maxmind.github.io/GeoIP2-php/
Apache License 2.0
2.34k stars 279 forks source link

Autoload unavailable #9

Closed jgarino closed 10 years ago

jgarino commented 10 years ago

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.

oschwald commented 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.

jgarino commented 10 years ago

Hi, I only use MaxMindDb now and it is enough to parse the CityLite mmdb. Problem solved.

Thanks very much.

bravo6608 commented 10 years ago

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

jgarino commented 10 years ago

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 !

jgarino commented 10 years ago

I haven't used composer at all... Just downloaded the package and use the PHP sources.

cubiclesoft commented 10 years ago

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.

oschwald commented 10 years ago

We released a phar archive version of the API for people who don't want to use Composer directly:

https://github.com/maxmind/GeoIP2-php#installing-via-phar

morrow95 commented 10 years ago

@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
?>
matthewslyman commented 10 years ago

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');//&deg;
        return $this->country_name().(is_null($this->city_name())?' ('.$latlong.')':'&#xa;'.$this->city_name().' ('.$latlong.')').'&#xa;&#x23F0;&nbsp;'.$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());
oschwald commented 10 years ago

@morrow95 if you remove the require_once 'vendor/autoload.php'; line, your code should work.

morrow95 commented 10 years ago

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.

oschwald commented 10 years ago

@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
morrow95 commented 10 years ago

It does... I shortly after my last comment I realized that phar wasn't enabled for some reason. Once enabled it was working great!

oschwald commented 10 years ago

Good to hear!