Share your knowledge and create a knowledgebase.
Sometimes you just need to know what country your site visitors are coming from—for example, if you’re trying to implement geo-targeted advertising. This article will show you how.
Sometimes you just need to know what country your site visitors are coming from—for example, if you’re trying to implement geo-targeted advertising. That’s where a tool like MaxMind’s GeoIP comes in—it lets you easily extract geographic data from your visitor’s IP address.
MaxMind makes available both commercial and free databases; the commercial ones are extremely precise and can get as fine-grained as the user’s city, while the free version can only identify the country of origin. We’ll use the free version in this article. If you need more detailed information, such as the remote client’s city and state of origin, you will need to purchase a more detailed database from MaxMind.
Getting started
To use it, you’ll have to first download the GeoIP Free Country file and extract it into a directory in your Web server. Then you’ll have to pick which language API to use with the database file. For simplicity, we’re going to use the pure PHP version because it doesn’t require any additional configuration or Apache modules. Remember to read the license terms before installing these on your Web site to ensure you are in compliance.
The code below demonstrates the basics of using the module (geoip.inc) to access the GeoIP Free Country database (GeoIP.dat). The example assumes both the PHP include and the country database file are in the same directory as the PHP file itself. You’ll have to change the paths as needed if this is not the case in your installation.
<?php // include functions include("geoip.inc"); // read GeoIP database $handle = geoip_open("GeoIP.dat", GEOIP_STANDARD); // map IP to country echo "IP address 62.149.130.132 located in " . geoip_country_name_by_addr($handle, "62.149.130.132") . " (country code " . geoip_country_code_by_addr($handle, "62.149.130.132") . ")"; // close database handler geoip_close($handle); // print compulsory license notice echo "<p> -- This product includes GeoIP data created by MaxMind, available from http://maxmind.com/ --"; ?> |
The sample code is pretty straightforward. After including the GeoIP PHP function library, the first step is to open the GeoIP database file with the geoip_open() function. This function accepts two arguments: the path to the database file and the type of database.
We then use the handle returned by the call to geoip_open() to obtain the two-letter country code and human-friendly name corresponding to the given IP address, via the geoip_country_code_by_addr() and geoip_country_code_by_name() functions, respectively. Both functions accept two arguments: the handle returned by geoip_open() and the IP address to resolve.
Once the required information is obtained, we close the database file with a call to geoip_close(). Simple as that.
Smarty Overview
The theoretical web development process is that: first the designer makes the interface, and breaks it down into HTML pieces for the programmer then the programmer implements the PHP business logic into the HTML.
That’s fine in theory, but in practice, from my experience, the client frequently comes with more requirements, or maybe more modifications to the design or to the business logic. When this happens , the HTML is modified (or words rebuilt ) programmer changes the code inside HTML.
The problem with this scenario is that the programmer needs to be on stand-by until the designer completes the layout and the HTML files. Another problem is that if there is a major design change then the programmer will change the code to fit in the new page. And that’s why I recommand Smarty. Smarty is a templating engine for PHP.
You can download it from http://www.phpinsider.com/php/code/Smarty/ or http://smarty.php.net . The installation process is very simple. Just read the documentation and follow up the instructions.
So what is Smarty ? Smarty is a set of PHP classes that compile the templates into PHP scripts. Smarty is a template language and a very useful tool for designers and programmers.
Smarty for Designers
Designers work with HTML files. To work with Smarty, you work with template files. These files are are made up of static content but combined with Smarty mark-up tags. All the template files have a .tpl extension. The Smarty template tags are enclosed within { and } delimiters.
Let’s consider the basic structure of a web page. There is a header, a middle part, and a footer. A template file that includes the header and the footer looks like this:
{include file="header.tpl"}
<form name="form1">
Label1 <input type="text" name="text1">
<input type="submit" value="submit">
</form>
{include file="footer.tpl"}
All the templates should reside in a single template directory. After calling a template for the first time, the compiled template will reside in templates_c.
Smarty language is very poweful. All the variables that come from PHP are identified in Smarty with {$Variable_Name} (we precede them with a $ sign). So if we have a variable in PHP that is called $MyName, then to print it in Smarty you have to write something like:
<html>
<body>
Welcome, {$MyName} <br>
</body>
</html>
The power of Smarty lies also in its flexibility. You can insert IFs and LOOPs into the template. The syntax for IF is:
{if <condition> }
html code
{else}
html code
{/if}
Let’s say you have a dynamic menu based on links. Depending on the link you click, you go to a specific page. So you get from PHP a variable $Menu with a integer value, depending on the page you are. The template looks like :
{if ($Menu == 1) }
Option 1
{else}
<a href="option1.php">Option 1</a>
{/if}
{if ($Menu == 2)}
Option 2
{else}
<a href="option2.php">Option 2</a>
{/if}
For coding a loop let’s suppose you get an array like the following from PHP :
<table>
<tr
{section name=user loop=$userID}
{if $smarty.section.user.iteration is odd}
bgcolor=#efefef
{else}
bgcolor=#ffffff
{/if}
>
<td> ID = {$userID[user]} </td>
<td> Name = {$name[user]} </td>
<td> Address = {$address[user]} </td>
</tr>
{sectionelse}
<tr>
<td>
There is no user.
</td>
</tr>
</section>
</table>
Iteration is an internal counter for Smarty. It helps us to know the current iteration of the section. I use this internal variable to make alternate row colors in the table by checking if current iteration value is odd or not (Note that iteration was added to Smarty from version 1.4.4).
An alternative for LOOPS is FOREACH which is used to loop over a single associative array.
<foreach from=$users item=current_user>
Name = {$current_user}
<foreachelse}
No user available.
</foreach>
The main difference between SECTION and FOREACH is that for SECTION you can start from a specific value, and can also set a step for the iteration, whereas for FOREACH you have to loop over all values.
Smarty for Programmers
The advantage for programmers is that they write the code in a PHP file without having to mix the instructions with HTML. Furthermore, if the designer changes the layout of a page the programmer doesn’t have to change the code to suit the new layout since the functionalities won’t change. You do your work in your files, assign to the templates all the values needed to print on the site and go out for a beer. You won’t get phone calls asking you to change a bit of code because the designer changed the layout and now a set of internal errors cropped up.
In the PHP file you need to include the Smarty class require ‘Smarty.class.php’. After that you need to instantiate the smarty with $smarty = new Smarty.
To assign a variable to the template you need to $smarty->assign(’UserName’, ‘John Doe’). After everything is finished you call the method to display the template $smarty->display(’index.tpl’).
A sample code looks like this (index.php) :
<?php
require ‘Smarty.class.php’;
$smarty = new Smarty;
$smarty->assign(’Username’, ‘John Doe’);
$smarty->display(’index.tpl’);
?>
The template (index.tpl) looks like this:
<html>
<body>
Welcome {$Username}
</body>
</html>
You can also create an array in PHP an pass it to the template:
$tmp = array ( ‘UID’=> ‘10′, &’Name’ => ‘John Doe’, ‘Address’=>’Home address’);
$smarty->assign(’info’, $tmp);
Sample Script
This script connects to a local database and select all the products from the ‘Products’ table. Then it passes all the values to the template, which prints them on the screen.
INDEX.PHP
<?php
require ‘Smarty.class.php’;
$smarty = new Smarty;
$hostname = "localhost";
$dbUser = "sqluser";
$dbPass = "sqlpass";
$dbName = "sqldb";
// connect to the database
$conn = mysql_connect($hostname, $dbUser, $dbPass) or die("Cannot connect to the database");
mysql_select_db($dbName);
$sql = "SELECT prodID, info FROM products ORDER BY prodID ASC";
// get all the products from the table
$res = mysql_query($sql);
$results = array();
$i=0;
while ($r=mysql_fetch_array($res)) {
$tmp = array(
‘prodID’ => $r['prodID'],
‘info’=> $r['info']
);
$results[$i++] = $tmp;
}
// pass the results to the template
$smarty->assign(’results’, $results);
// load the template
$smarty->display(’index.tpl’);
?>
INDEX.TPL
<html>
<body>
Here’s a table with the results: <br>
<table cellpadding=1 cellspacing=0 border=0 width=100%>
{section name=nr loop=$results}
<tr {if $smarty.section.nr.iteration is odd} bgcolor="#efefef"{/if}>
<td class=fb width=15%>
<nobr><a href=”show-product.php?id={$results[nr].prodID}">Press here</a>
<td class=fb width=29%><a href="show.php?id={$results[nr].prodID}"
{popup inarray=$smarty.section.nr.iteration}
>{$results[nr].info}</a></td>
</tr>
{sectionelse}
<tr><td align="center"><br><b>no product </b> <br> </td></tr>
{/section}
</table>
<br>
Here’s a select with the results: <br>
<select name="mys">
{section name=nr loop=$results}
<option value="{$results[nr].prodID}">{$results[nr].info}</option>
{/section}
</select>
</body>
</html>
Summary
Smarty is a great tool for both designers and developers. By using Smarty you can reduce the site development and maintenance times. If you are a developer you no longer need to mix PHP code with HTML code. Just take care of business logic and leave the HTML to the designer.
The PHP Extension and Application Repository, or PEAR, is a framework and distribution system for PHP code components. The PEAR project seeks to provide a structured library of code, maintain a system for distributing code and for managing code packages, and promote a standard coding style. Though community-driven, the PEAR project has a PEAR Group which serves as the governing body and takes care of administrative tasks. Each PEAR code package comprises an independent project under the PEAR umbrella. It has its own development team, versioning-control and documentation.
A PEAR package is distributed as a gzipped tar file. It can consist of source code or binaries or both. Many PEAR packages can readily be used by developers as ordinary third party code via simple include statements in PHP. More elegantly, the PEAR installer which comes with PHP by default may be used to install PEAR packages so that the extra functionality provided by the package appears as an integrated part of the PHP installation. Unlike the Comprehensive Perl Archive Network (CPAN) archives, which PEAR took as its model, PEAR packages do not have implicit dependencies so that a package’s placement in the PEAR package tree does not relate to code dependencies. Rather, PEAR packages must explicitly declare all dependencies on other PEAR packages.
The PEAR base classes contain code for simulating object-oriented destructors and consistent error-handling. Packages exist for many basic PHP functions including authentication, caching, database access, encryption, configuration, HTML, web services and XML.
PECL (PHP Extension Community Library) is conceptually very similar to PEAR, and indeed PECL modules are installed with the PEAR Package Manager. PECL contains C extensions for compiling into PHP. As C programs , PECL extensions run more efficiently than PEAR packages. PECL includes modules for XML-parsing, access to additional databases, mail-parsing, embedding Perl or Python in PHP scripts and for compiling PHP scripts. Originally PECL was called the PEAR Extension Code Library, but it now operates independently of PEAR.
List of package categories
* Authentication
* Benchmarking
* Caching
* Configuration
* Console
* Database
* Date & Time
* Encryption
* Event
* File Formats
* File System
* Gtk Components
* Gtk2 Components
* HTML
* HTTP
* Images
* Internationalization
* Logging
* Mail
* Math
* Networking
* Numbers
* Payment
* PEAR
* PHP
* Processing
* Science
* Semantic Web
* Streams
* Structures
* System
* Text
* Tools and Utilities
* Validate
* Web Services
* XML
Following are the websites list who provide free php scripts. You can find lots of information about PHP as well as free code samples, code galleries, and free scripts for download at these and other sites. There may be some premium php scripts which may come for a price but overall the list is good enough.
http://www.scripts.com/php-scripts/
http://www.best-php-scripts.com/
http://www.thefreecountry.com/php/index.shtml
http://www.phpbuilder.com/snippet/
http://www.hotscripts.com/PHP/
http://www.phpresourceindex.com/
I would be adding more to the list soon….
The following example illustrates how to use an external entity reference handler to include and parse other documents, as well as how PIs can be processed, and a way of determining "trust" for PIs containing code.
Consider the following XML’s
< ?xml version=’1.0′?>
< !DOCTYPE chapter SYSTEM "/just/a/test.dtd" [
<!ENTITY plainEntity "FOO entity">
< !ENTITY systemEntity SYSTEM "xmltest2.xml">
]>
<chapter>
<title>Title &plainEntity;</title>
<para>
<informaltable>
<tgroup cols="3">
<tbody>
<row><entry>a1</entry><entry morerows="1">b1</entry><entry>c1</entry></row>
<row><entry>a2</entry><entry>c2</entry></row>
<row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row>
</tbody>
</tgroup>
</informaltable>
</para>
&systemEntity;
<section id="about">
<title>About this Document</title>
<para>
<!– this is a comment –>
< ?php echo ‘Hi! This is PHP version ‘ . phpversion(); ?>
</para>
</section>
</chapter>
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY testEnt "test entity">
]>
<foo>
<element attrib="value"/>
&testEnt;
<?php echo "This is some more PHP code being executed."; ?>
</foo>
The following code shows how we can parse the above XML file using PHP
< ?php
$file = "xmltest.xml";
function trustedFile($file)
{
// only trust local files owned by ourselves
if (!eregi("^([a-z]+)://", $file)
&& fileowner($file) == getmyuid()) {
return true;
}
return false;
}
function startElement($parser, $name, $attribs)
{
echo "<<font color=\"#0000cc\">$name";
if (count($attribs)) {
foreach ($attribs as $k => $v) {
echo " <font color=\"#009900\">$k</font>=\"<font color=\"#990000\">$v</font>\"";
}
}
echo ">";
}
function endElement($parser, $name)
{
echo "</<font color=\"#0000cc\">$name</font>>";
}
function characterData($parser, $data)
{
echo "<b>$data</b>";
}
function PIHandler($parser, $target, $data)
{
switch (strtolower($target)) {
case "php":
global $parser_file;
// If the parsed document is "trusted", we say it is safe
// to execute PHP code inside it. If not, display the code
// instead.
if (trustedFile($parser_file[$parser])) {
eval($data);
} else {
printf("Untrusted PHP code: <i>%s</i>",
htmlspecialchars($data));
}
break;
}
}
function defaultHandler($parser, $data)
{
if (substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";") {
printf(’<font color="#aa00aa">%s</font>’,
htmlspecialchars($data));
} else {
printf(’<font size="-1">%s</font>’,
htmlspecialchars($data));
}
}
function externalEntityRefHandler($parser, $openEntityNames, $base, $systemId,
$publicId) {
if ($systemId) {
if (!list($parser, $fp) = new_xml_parser($systemId)) {
printf("Could not open entity %s at %s\n", $openEntityNames,
$systemId);
return false;
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($parser, $data, feof($fp))) {
printf("XML error: %s at line %d while parsing entity %s\n",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser), $openEntityNames);
xml_parser_free($parser);
return false;
}
}
xml_parser_free($parser);
return true;
}
return false;
}
function new_xml_parser($file)
{
global $parser_file;
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 1);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
xml_set_processing_instruction_handler($xml_parser, "PIHandler");
xml_set_default_handler($xml_parser, "defaultHandler");
xml_set_external_entity_ref_handler($xml_parser, "externalEntityRefHandler");
if (!($fp = @fopen($file, "r"))) {
return false;
}
if (!is_array($parser_file)) {
settype($parser_file, "array");
}
$parser_file[$xml_parser] = $file;
return array($xml_parser, $fp);
}
if (!(list($xml_parser, $fp) = new_xml_parser($file))) {
die("could not open XML input");
}
echo "<pre>";
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d\n",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
echo "</pre>";
echo "parse complete\n";
xml_parser_free($xml_parser);
?>
I hope this will help. Your comments are welcome.