Fatal error: Declaration of GeoIp2\WebService\Client::country(string $ipAddress = 'me'): GeoIp2\Model\Country must be compatible with GeoIp2\ProviderInterface::country($ipAddress) #170
Description
Activity
Would you be able to provide some more information? How can we reproduce this? What version of PHP are you using? Do you have any particular setting that might affect this? The output of
php -imay be useful.Sorry! I missed to share the basic info. I am trying to implement MaxMind on staging server and that is password protected. Therefore, you wouldn't be able to reproduce this. Please see the screenshot below:
I am trying to use the MaxMind Web Service with the code snippet given below:
$client = new Client(
'XXXXXX',
'xxxxxxxxxxxxxxxx',
[['en'],
['host' => 'geolite.info']
);$geodata = [];
try{
$record = $client->city($ip); // Get the ip by calling a function
if(!empty($record)){
$geodata['content'] = json_encode(
(object) [
"country_code" => h($record->country->isoCode),
"country_name" => h($record->country->name),
"city" => h($record->city->name),
"postal" => h($record->postal->code),
"latitude" => h($record->location->latitude),
"longitude" => h($record->location->longitude),
"IPv4" => h($record->traits->ipAddress),
"state" => h($record->mostSpecificSubdivision->name)
]
);
}
}catch(\Exception $e){
$geodata['error'] = json_encode(
[
'message' => $e->getMessage()
]
);
}My PHP version is 7.2. I don't think any particular setting is there. Reason is this is working fine locally but when I try this on staging server, I get the fatal error. My PHP version on local env is 7.4, but I read that MaxMind supports PHP 7.2 or higher version, therefore, I think this should work on staging as well.
Is it possible you have two different versions of this library being loaded on your staging server? PHP 7.2 is currently supported. I just confirmed that it works by running a slightly modified version of your code on 7.2.34.
Currently, I have a single version and if needed I can put another modified version as you have mentioned above. What kind of modifications will be there?
Just FYI.. I have used this repo to get the library.
I am not sure what could be the problem in that case. I've seen issues like this previously when someone was using a WordPress plugin that loads its own version of this code, which causes class mismatches like this. If you can reduce it to a simple test case, I would be happy to look at it further.
Also, my modifications to your code were just to fix typos like
[['en'],, add an account ID and license key, and add some debugging output.I am not sure what could be the problem in that case. I've seen issues like this previously when someone was using a WordPress plugin that loads its own version of this code, which causes class mismatches like this. If you can reduce it to a simple test case, I would be happy to look at it further.
Yeah, I got that. I have checked with enabling all the plugins being used on staging and it still works on local env. In addition, I am using a few plugins only and seems that they are fine.
Also, my modifications to your code were just to fix typos like
[['en'],, add an account ID and license key, and add some debugging output.Yeah, I can see that typo, but it looks fine in my source code. Not sure, how this got added.
This works fine while using DB method but for the case of
webservice, throws the error.Below code (database approach) works fine on staging:
$client = new Reader(DIR . '/maxmind/geolite2/db/GeoLite2-City.mmdb'); //GeoLite2-City_20210824
Are you using this in a WordPress, a CMS, or some other framework? What plugins are you using?
Yes, I am using this in WordPress. Customized the WordPress and implemented the MVC model into the system.
Following plugins are being used:
- Advanced Custom Fields PRO
- Classic Editor
- Elementor
- Elementor PRO
- Prevent XSS Vulnerability
- Reading Time WP
- Simple 301 Redirects
- SVG Support
- Timber
- W3 Total Cache
- Wordfence Security
- WordPress Sentry
- WP Session Manager
- SendGrid
- Options Framework
I believe Wordfence Security uses this library. It looks like their latest release uses 2.9.0 of
geoip2/geoip2. They are using it for reading a GeoLite2 database, which will load an older version ofGeoIp2\ProviderInterface. This will cause the error you are seeing when you try to load 2.11.0 in your own code.You could try to match the version of
geoip2/geoip2they use.Okay, thanks a lot for looking into this. I will try your suggestion.
I am going to close this as there is nothing we can do about it. Plugin authors should probably be using something like PHP-Scoper on their dependencies to prevent collisions like this.
Keep in mind that GeoIp2 does not scopper PHP Scoper out of the box. You'll need to use patchers (a PHP Scoper feature) to get this done. This is because the library code constructs namspace/class strings which PHP Scoper cannot target.
Here's an example I created to patch Reader.php, though it appears there are other files that use
$class = 'GeoIp2...pattern such as Client.php:'patchers' => [ static function (string $filePath, string $prefix, string $contents): string { $parts = explode('vendor', $filePath); // Fix an issue with geoip2 where the reader has string class names if ($parts[1] === '/geoip2/geoip2/src/Database/Reader.php') { return preg_replace( '%\$class = \'GeoIp2%', '$class = \'' . $prefix . '\\\\GeoIp2', $contents ); } return $contents; }, ],
If you open a separate issue, I think we could easily fix the problem with the stringy class names.
Reacted by Andrew Mead
