![]() |
|
Snippets |
|
This snippet allows you to retrieve the country of the visitor using the IP number of the visitor. It will also become available as a symfony Plugin.
Very handy when you are developing a internationalized application. You can use the ISO code in lowercase to set the interface language. Like this:
$lang = strtolower(Country::getIso2WithIp(Country::getIpAddress()))
By passing the IP number to a function, you'll get the following information: - ISO 3166 Code, 2 characters, might be used to set the culture - Country, 20 characters
The IP data is imported from the webnet77 (http://software77.net/cgi-bin/ip-country/geo-ip.pl) database, probably the most frequently updated database on the web.
Data is stored on your server, that means that retrieving data is a lot faster compared to the already existing plugin sfIp2Country, which uses a web request.
config/schema.xml:
<table name="YOURDB_country" phpName="Country"> <column name="ipfrom" type="bigint" size="20" required="true" primaryKey="true" /> <column name="ipto" type="bigint" size="20" /> <column name="registry" type="varchar" size="7" /> <column name="assigned" type="varchar" size="8" /> <column name="iso2" type="varchar" size="2" /> <column name="iso3" type="varchar" size="3" /> <column name="country" type="varchar" size="20" /> </table>
Do a build-model and whatever is needed.
Additions to lib/model/country.php
static function getIpAddress() { // Get the ip v4 address if (getenv("HTTP_CLIENT_IP")) $ipaddr = getenv("HTTP_CLIENT_IP"); else if(getenv("HTTP_X_FORWARDED_FOR")) $ipaddr = getenv("HTTP_X_FORWARDED_FOR"); else if(getenv("REMOTE_ADDR")) $ipaddr = getenv("REMOTE_ADDR"); else $ipaddr = "127.0.0.1"; // not found, make it localhost return $ipaddr; } static function retrievePkByIp($ipaddr) { // Make IP numerical $ipnum = sprintf("%u", ip2long($ipaddr)); // lookup IP address $c = new Criteria(); $c->add(CountryPeer::IPFROM, "'$ipnum' >= ".CountryPeer::IPFROM." and "."'$ipnum' <= ".CountryPeer::IPTO, Criteria::CUSTOM); $rs = CountryPeer::doSelectRS($c); $pk = 0; while ($rs->next()){ $pk = $rs->getString(1); } return $pk; } static function getIso2WithIp($ipaddr) { // Make IP numerical $ipnum = sprintf("%u", ip2long($ipaddr)); // lookup IP address $c = new Criteria(); $c->add(CountryPeer::IPFROM, "'$ipnum' >= ".CountryPeer::IPFROM." and "."'$ipnum' <= ".CountryPeer::IPTO, Criteria::CUSTOM); $rs = CountryPeer::doSelectRS($c); $iso2 = "EN"; // initialize with your default country while ($rs->next()){ $iso2 = $rs->getString(5); } return $iso2; }
Helper to demonstrate the works: \apps\frontend\lib\helper\CountryHelper.php
<?php function display_ipinfo() { // Get IP address and make numeric $ipaddr = Country::getIpAddress(); $ipnum = sprintf("%u", ip2long($ipaddr)); // Retrieve from database $country = CountryPeer::retrieveByPk(Country::retrievePkByIp($ipaddr)); // Output $o = '<p>'; $o .= 'Your IP number: ' . ' ' . $ipaddr . '<br />'; $o .= 'Your IP numerical: ' . $ipnum . '<br />'; $o .= 'Data retrieved from IP database:<br />'; if ($country) // found { $o .= 'ISO code: ' . $country->getIso2() . '<br />'; $o .= 'Country: ' . ' ' . $country->getCountry(); } else // not found { $o .= 'Your IP number was not found in the IP-database'; } $o .= '</p>'; echo $o; }
Code to call the demo function in the helper:
<?php use_helper('Country'); ?> <?php display_ipinfo() ?>
I load my data with a Cron job, the SQL statement is as follows:
LOAD DATA INFILE 'YOURPATH_IpToCountry.csv' REPLACE INTO TABLE YOURDB_country FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n'
Demo at http://www.noorden.com/en/my+symfony+php+projects/project-ip-number-to-country.html
Comments on this snippet
good mornig!
very very good! im' searching for this in these days.
Then, how to automatically upload every day o week the our copy db whit original update geo-ip? there are any xml online that point to db status csv o gzipped db file?
thanks again
Dear Killian,
I assume that you want to use the Geo IP data of Maxmind. Should be simple enough, see structure of CSV on http://www.maxmind.com/app/csv
I recommend that you still use LOAD DATA to load the file in the SQL database. LOAD DATA is very fast, loading the CSV file with more then 80.000 records takes about 1,4 seconds.
Kind regards, Frank
** Posted again, my 2nd comment is nowhere to be found!! **
Dear Killian, I probably misunderstood your question. Scrap my remark about Maxmind.
I still recommend that you LOAD DATA to load the data in the SQL database.
You can find an example script by Georg Jordt, download and import, on http://software77.net/geoip-software.htm
Running the script as automated task should be simple: Linux/Unix server: search on Google with argument call php script cron Windows server: search on Google with argument call php script as task from windows
Kind regards,
Frank