![]() |
|
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
format a phone number with 7, 10, or 11 digits. also can convert phone number letters to numbers
lib/helpers/PhoneHelper.php
<?php function format_phone($phone = '', $convert = false, $trim = true) { // If we have not entered a phone number just return empty if (empty($phone)) { return ''; } // Strip out any extra characters that we do not need only keep letters and numbers $phone = preg_replace("/[^0-9A-Za-z]/", "", $phone); // Do we want to convert phone numbers with letters to their number equivalent? // Samples are: 1-800-TERMINIX, 1-800-FLOWERS, 1-800-Petmeds if ($convert == true) { $replace = array('2'=>array('a','b','c'), '3'=>array('d','e','f'), '4'=>array('g','h','i'), '5'=>array('j','k','l'), '6'=>array('m','n','o'), '7'=>array('p','q','r','s'), '8'=>array('t','u','v'), '9'=>array('w','x','y','z')); // Replace each letter with a number // Notice this is case insensitive with the str_ireplace instead of str_replace foreach($replace as $digit=>$letters) { $phone = str_ireplace($letters, $digit, $phone); } } // If we have a number longer than 11 digits cut the string down to only 11 // This is also only ran if we want to limit only to 11 characters if ($trim == true && strlen($phone)>11) { $phone = substr($phone, 0, 11); } // Perform phone number formatting here if (strlen($phone) == 7) { return preg_replace("/([0-9a-zA-Z]{3})([0-9a-zA-Z]{4})/", "$1-$2", $phone); } elseif (strlen($phone) == 10) { return preg_replace("/([0-9a-zA-Z]{3})([0-9a-zA-Z]{3})([0-9a-zA-Z]{4})/", "($1) $2-$3", $phone); } elseif (strlen($phone) == 11) { return preg_replace("/([0-9a-zA-Z]{1})([0-9a-zA-Z]{3})([0-9a-zA-Z]{3})([0-9a-zA-Z]{4})/", "$1($2) $3-$4", $phone); } // Return original phone if not 7, 10 or 11 digits long return $phone; }
Here are some extra helpers that I don't think are in symfony anywhere. They would fit rather nicely in the 'Number' helper group.
<!-- someTemplateSuccess.php --> <?php use_helper('NumberPlus') ?> <table> <thead> <tr> <th>Name</th> <th>Phone</th> <th>Credit Card</th> <th>Exp.</th> <th>Income</th> <th>SSN</th> </tr> </thead> <tbody> <?php foreach ($users as $user): ?> <tr> <td><?php echo $user->getName() ?></td> <td><?php echo format_phone($user->getPhone()) ?></td> <td><?php echo mask_credit_card($user->getCc()) ?></td> <td><?php echo format_exp($user->getExp()) ?></td> <td><?php echo format_usd($user->getIncome()) ?></td> <td><?php echo format_ssn($user->getSsn()) ?></td> </tr> <?php endforeach; ?> </tbody> </table>
<?php /** * Formats a number by injecting nonnumeric characters in a specified format * into the string in the positions they appear in the format. * * <strong>Example:</strong> * <code> * echo format_string('1234567890', '(000) 000-0000'); * // => (123) 456-7890 * * echo format_string('1234567890', '000.000.0000'); * // => 123.456.7890 * </code> * * @param string the string to format * @param string the format to apply * @return the formatted string */ function format_string($string, $format) { if ($format == '' || $string == '') return $string; $result = ''; $fpos = 0; $spos = 0; while ((strlen($format) - 1) >= $fpos) { if (is_alphanumeric(substr($format, $fpos, 1))) { $result .= substr($string, $spos, 1); $spos++; } else { $result .= substr($format, $fpos, 1); } $fpos++; } return $result; } /** * Transforms a number by masking characters in a specified mask format, * and ignoring characters that should be injected into the string without * matching a character from the original string (defaults to space). * * <strong>Example:</strong> * <code> * echo mask_string('1234567812345678', '************0000'); * // => ************5678 * * echo mask_string('1234567812345678', '**** **** **** 0000'); * // => **** **** **** 5678 * * echo mask_string('1234567812345678', '**** - **** - **** - 0000', ' -'); * // => **** - **** - **** - 5678 * </code> * * @param string the string to transform * @param string the mask format * @param string a string (defaults to a single space) containing characters to ignore in the format * @return string the masked string */ function mask_string($string, $format, $ignore = ' ') { if ($format == '' || $string == '') return $string; $result = ''; $fpos = 0; $spos = 0; while ((strlen($format) - 1) >= $fpos) { if (is_alphanumeric(substr($format, $fpos, 1))) { $result .= substr($string, $spos, 1); $spos++; } else { $result .= substr($format, $fpos, 1); if (strpos($ignore, substr($format, $fpos, 1)) === false) $spos++; } $fpos++; } return $result; } /** * Formats a phone number. * * @param string the unformatted phone number to format * @param string the format to use, defaults to '(000) 000-0000' * @return string the formatted string * * @see format_string */ function format_phone($string, $format = '(000) 000-0000') { return format_string($string, $format); } /** * Formats a variable length phone number, using a standard format. * * <strong>Example:</strong> * <code> * echo smart_format_phone('1234567'); * // => 123-4567 * * echo smart_format_phone('1234567890'); * // => (123) 456-7890 * * echo smart_format_phone('91234567890'); * // => 9 (123) 456-7890 * * echo smart_format_phone('123456'); * // => 123456 * </code> * * @param string the unformatted phone number to format * * @see format_string */ function smart_format_phone($string) { switch (strlen($string)) { case 7: return format_string($string, '000-0000'); case 10: return format_string($string, '(000) 000-0000'); case 11: return format_string($string, '0 (000) 000-0000'); default: return $string; } } /** * Formats a U.S. Social Security Number. * * <strong>Example:</strong> * <code> * echo format_ssn('123456789'); * // => 123-45-6789 * </code> * * @param string the unformatted ssn to format * @param string the format to use, defaults to '000-00-0000' * * @see format_string */ function format_ssn($string, $format = '000-00-0000') { return format_string($string, $format); } /** * Formats a credit card expiration string. Expects 4-digit string (MMYY). * * @param string the unformatted expiration string to format * @param string the format to use, defaults to '00-00' * * @see format_string */ function format_exp($string, $format = '00-00') { return format_string($string, $format); } /** * Formats (masks) a credit card. * * @param string the unformatted credit card number to format * @param string the format to use, defaults to '**** **** **** 0000' * * @see mask_string */ function mask_credit_card($string, $format = '**** **** **** 0000') { return mask_string($string, $format); } /** * Formats a USD currency value with two decimal places and a dollar sign. * * @param string the unformatted amount to format * @param string the format to use, defaults to '$%0.2f' * * @see sprintf */ function format_usd($money, $dollar = true, $format = '%0.2f') { return ($dollar ? '$' : '') . sprintf($format, $money); } /** * Determines if a string has only alpha/numeric characters. * * @param string the string to check as alpha/numeric * * @see is_numeric * @see preg_match */ function is_alphanumeric($string) { return preg_match('/[0-9a-zA-Z]/', $string); }
NOTE: Place this in something like myproj/apps/myapp/lib/helper/NumberPlusHelper.php