Code snippets for symfony 1.x

Navigation

IP number to country

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: '  . '&nbsp;&nbsp;&nbsp;' . $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: ' . '&nbsp;&nbsp;' . $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

by Frank van Noorden on 2008-03-02, tagged country  database  ip  iso  local  number 

Comments on this snippet

gravatar icon
#1 kilian c. on 2008-03-09 at 09:51

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

gravatar icon
#2 Frank van Noorden on 2008-03-13 at 12:34

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

gravatar icon
#3 Frank van Noorden on 2008-03-13 at 01:21

** 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