地理定位查询主要可分为两个步骤:第一,获取待查询的IP;第二,利用MaxMind? API进行查询并返回查询结果。本例中数据比较简单,因此可以把查询结果直接以Javascript字符串的形式返回给客户端,用eval调用即可。下面将详细介绍上述步骤。
1.获取待查询的IP
首先,在文件开始的部分引入MaxMind? API的库文件。
-
<?php
-
//导入库文件
-
include("geoipcity.inc");
-
include("geoipregionvars.php")
-
?>
如果未传递任何参数,则使用当前访客的IP,如此就可以在加载的时候使用显示当前访客的信息了。代码如下。
-
//接上面程序
-
//获取客户端IP的函数
-
function getClientIP()
-
{
-
if (isset($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"]))
-
{
-
$ip = $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"];
-
}
-
elseif (isset($HTTP_SERVER_VARS["HTTP_CLIENT_IP"]))
-
{
-
$ip = $HTTP_SERVER_VARS["HTTP_CLIENT_IP"];
-
}
-
elseif (isset($HTTP_SERVER_VARS["REMOTE_ADDR"]))
-
{
-
$ip = $HTTP_SERVER_VARS["REMOTE_ADDR"];
-
}
-
elseif (getenv("HTTP_X_FORWARDED_FOR"))
-
{
-
$ip = getenv("HTTP_X_FORWARDED_FOR");
-
}
-
elseif (getenv("HTTP_CLIENT_IP"))
-
{
-
$ip = getenv("HTTP_CLIENT_IP");
-
}
-
elseif (getenv("REMOTE_ADDR"))
-
{
-
$ip = getenv("REMOTE_ADDR");
-
}
-
else
-
{
-
$ip = false;
-
}
-
return $ip;
-
}
-
-
//如果传递的查询参数为空
-
if(empty($_GET['q']))
-
{
-
$ip = getClientIP();
-
if (!isset($ip))
-
{
-
echo 'alert("Cannot get your IP address!");';
-
die();
-
}
-
}
如果有参数传递,则判断是否为IP或域名信息。如果都不是,报错,终止查询。代码如下。
-
//接上面程序
-
//如果传递的查询参数不为空
-
else
-
{ //探测字符串是否为IP的正则表达式
-
$pattern = "/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\
.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2
[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/";
-
-
if(preg_match($pattern, $_GET['q'])) //如果查询的信息为IP
-
{
-
$ip = $_GET['q'];
-
}
-
else //如果查询的信息为域名
-
{
-
$ip = gethostbyname($_GET['q']);
//若域名查询成功,则返回的字符串为IP
-
if(!preg_match($pattern, $ip))
//检测是否返回IP,若未返回IP,即域名查询失败,报错
-
{
-
echo 'alert("Invalid Input!"); ';
-
die();
-
}
-
}
-
}
经过以上一系列处理,就可以从参数中获取真实的IP用于查询了。
2.通过IP获取地理信息
利用MaxMind?取得某IP的地理信息是相对容易的,查询的结果是一个结构体,包含国家代码、国家名称、城市名称和城市经纬度等信息。下面对其中元素进行一一说明。
country_code - 国家代码(两位),如中国为CN。
country_code3 - 国家代码(三位),如中国为CHN。
country_name - 国家名称(英文),如中国为China。
region - 区域代码,通过$GEOIP_REGION_NAME[$record->country_code] [$record->region]可获得区域的名称。对于中国,region得到的是省级行政区的名称,如$GEOIP_REGION_NAME["CN"]["01"]对应的行政区即位Anhui(安徽)。
city - 城市名称。
postal_code - 邮编,仅美国可用。
latitude - 纬度。
longitude - 经度。
dma_code - DMA代码,仅美国可用。
area_code - 地区代码,仅美国可用。
了解数据的组织结构后就可以方便地使用其中的数据了。代码如下:
-
//接上面程序
-
-
//如果取消下一行将使用共享内存打开GeoLiteCity数据库,
可加快查询。但前提是服务器支持共享内存
-
//$gi = geoip_open("./GeoLiteCity.dat",GEOIP_MEMORY_CACHE);
-
-
//以常规方式打开GeoLiteCity数据库,一般情况下都可以使用
-
$gi = geoip_open("./GeoLiteCity.dat",GEOIP_STANDARD);
-
-
//以上是假定GeoLiteCity数据库和PHP文件在同一个目录,
故使用"./GeoLiteCity.dat"为路径
-
//如果不是,请改为实际目录
-
-
//获取IP的信息
-
$record = geoip_record_by_addr($gi, $ip);
-
//关闭数据库
-
geoip_close($gi);
-
-
//如果获取了相关数据
-
if($record)
-
{
-
echo 'loadGeoInfo('.
-
'"'. $_GET['q'] .'",'.
//原始查询信息
-
'"'. $ip .'",'. //被查IP
-
'"'. $record->country_code
.'",'. //国家代码(两位)
-
'"'. $record->country_code3
.'",'. //国家代码(三位)
-
'"'. $record->country_name
.'",'. //国家名称
-
'"'. $GEOIP_REGION_NAME
[$record->country_code] [$record->region] .'",'.
//地区名称
-
'"'. $record->city .'",'.
//城市名称
-
$record->latitude .','. //纬度
-
$record->longitude .')'; //经度
-
//如果数据库中不存在相关数据
-
else
-
{
-
echo 'alert("The Information for '.$ip.' is not available now!"); ';
-
}
-
?>
将以上代码整合到一起,保存为search.php,放到本程序的主目录中(search.php完整代码在光盘中本章节目录里可以找到)。
在浏览器中输入http://服务器地址/程序所在路径/search.php?q=google.com,应该会显示与下面信息类似的输出结果。
loadGeoInfo("google.com", "64.233.187.99", "US", "USA", "United States", "California", "Mountain View", 37.4192,-122.0574)
而输入http://服务器地址/程序所在路径/search.php?q=202.114.64.139,则输出应该和下面类似。
loadGeoInfo("202.114.64.139", "202.114.64.139", "CN", "CHN", "China", "Hubei", "Wuhan" ,30.5833, 114.2667)