designing4u.de Yet Another Coding Blog

19May/083

Class for retrieving region, city and geolocation

For one of the social platforms I was creating I had to provide profile display according to the location from which the request was made. There are plenty services in the internet, which provide you an accurate database, which will translate IP address into region, city and geographical lengths. I didn't want to spend any money for this kind of service, so I decided to find a free solution for this task. However, none of the services existing in the internet provides you 100% accuracy, the one that I've found locates my IP correctly. It would be nice, if you could give me some feedback, if this class is working for you as good as it works for me. This example requires URL file-access to be enabled on your server, because we will request the XML data through URL call. In this example we will also use SimpleXMLElement class, which should be enable by default in PHP5, to translate our XML file into an object. We will then recurse received object into a suitable array.

Unfortunately my provider doesn't enable URL file-access, therefore I wont be able to show you, how this example works. I tested it on different server though and you can trust me, it works.

The first thing you need to do is to go to getpos.de and register a new account. Unfortunately this service is only in German, but I don't think you should have any problem with registering a new account. Let's take a look at our class:
[source:php]
class Geolocation {

private $ip;
private $xml_data;
private $xml;

public $geo;
public $error;

function __construct($ip) {
$this->ip = $ip;
$this->xml_data = simplexml_load_file("http://services.getpos.de/ip2loc.asmx/GetIPPosition?UserName=YOUR_USERNAME&Password=YOUR_PASSWORD&IPAddress=".$this->ip);
}

public function findGeo() {
if(!$this->xml_data) {
$this->error = "service unavailable";
return false;
}
$this->xml = new SimpleXMLElement($this->xml_data);
$this->RecurseXML($this->xml,$this->geo);
}

private function RecurseXML($xml,$vals,$parent=""){
$child_count = 0;
foreach($xml as $key=>$value) {
$child_count++;
$k = ($parent == "") ? (string)$key : $parent.".".(string)$key;

if($this->RecurseXML($value,$this->geo,$k) == 0)
$this->geo[$k] = (string)$value;
}
return $child_count;
}
}
[/source]
We define IP address, XML data and an instance of SimpleXMLObject as private properties and our error handler and actual geo data as public properties. In our constructor we pass IP address and we use simplexml_load_file function to interpret the XML file into an object. Obviously you need to replace YOUR_USERNAME and YOUR_PASSWORD with the information you will use to register at getpos.de. In findGeo() method we first check, if the service is available, and if not we show error message. If our service is available though, we instantiate SimpleXMLObject with the XML data. We than use RecurseXML() method to translate our object into a suitable array. The credit for RecurseXML() goes to transglobe at gmx dot de. I found this function in the comments section of PHP manual and changed it a little bit to suit our needs.

Let's take a closer look, how to use our class:
[source:php]
include("geolocation.class.php");
$geo = new Geolocation($_SERVER['REMOTE_ADDR']);

$geo->findGeo();
echo (isset($geo->error)) ? $geo->error : '';

echo "geo['returncode']:".$geo->geo['returncode']."
";
echo "geo['country.code']:".$geo->geo['country.code']."
";
echo "geo['country.name']:".$geo->geo['country.name']."
";
echo "geo['region.code']:".$geo->geo['region.code']."
";
echo "geo['region.name']:".$geo->geo['region.name']."
";
echo "geo['city']:".$geo->geo['city']."
";
echo "geo['position.longitude']:".$geo->geo['position.longitude']."
";
echo "geo['position.latitude']:".$geo->geo['position.latitude']."
";
echo "geo['returncode']:".$geo->geo['returncode']."
";
[/source]
We include our class and instantiate it with the remote address of a visitor. We than call findGeo() method, which will translate the IP address for us. We can than echo our results or just use them to display relevant information for our users. Obviously, if a user is connected through a proxy or some AOL users in Europe, who are connected through American servers, this class wont retrieve correct information. You need to take into consideration though, that about 65% of your visitors will get correct content. I hope it is clear enough. If you encounter any problems with this class please let me know. As mentioned before, it would be also nice if you could give me any feedback about the accuracy of this service.

Comments (3) Trackbacks (1)
  1. Thanks a lot for this help in exames!!! It’s a wonderfull class to use this service of ‘getpos.de’.

  2. cant you just cURL the XML file? wouldn’t that avoid the issue of URL file-access?

  3. Hi Andrew,

    yes of course you can use cURL to retrieve XML data, but the server configuration of getpos allows URL file-access.

    On the other hand I tried to use cURL to retrieve the XML data from getpos and they are returned as htmlentities (at least parts of them).

    My summary would be that first of all that solution was written to work with getpos service. Second of all, as long as a getpos server configuration allows URL access simplexml_load_file function is faster to use with getpos service, but if you feel like it, you can play with curl_setopt to find a perfect configuration to perform the same task.


Leave a comment

(required)