地理定位查詢(xún)主要可分為兩個(gè)步驟:第一,獲取待查詢(xún)的IP;第二,利用MaxMind? API進(jìn)行查詢(xún)并返回查詢(xún)結(jié)果。本例中數(shù)據(jù)比較簡(jiǎn)單,因此可以把查詢(xún)結(jié)果直接以Javascript字符串的形式返回給客戶(hù)端,用eval調(diào)用即可。下面將詳細(xì)介紹上述步驟。
1.獲取待查詢(xún)的IP
首先,在文件開(kāi)始的部分引入MaxMind? API的庫(kù)文件。
-
<?php
-
//導(dǎo)入庫(kù)文件
-
include("geoipcity.inc");
-
include("geoipregionvars.php")
-
?>
如果未傳遞任何參數(shù),則使用當(dāng)前訪客的IP,如此就可以在加載的時(shí)候使用顯示當(dāng)前訪客的信息了。代碼如下。
-
//接上面程序
-
//獲取客戶(hù)端IP的函數(shù)
-
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;
-
}
-
-
//如果傳遞的查詢(xún)參數(shù)為空
-
if(empty($_GET['q']))
-
{
-
$ip = getClientIP();
-
if (!isset($ip))
-
{
-
echo 'alert("Cannot get your IP address!");';
-
die();
-
}
-
}
如果有參數(shù)傳遞,則判斷是否為IP或域名信息。如果都不是,報(bào)錯(cuò),終止查詢(xún)。代碼如下。
-
//接上面程序
-
//如果傳遞的查詢(xún)參數(shù)不為空
-
else
-
{ //探測(cè)字符串是否為IP的正則表達(dá)式
-
$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'])) //如果查詢(xún)的信息為IP
-
{
-
$ip = $_GET['q'];
-
}
-
else //如果查詢(xún)的信息為域名
-
{
-
$ip = gethostbyname($_GET['q']);
//若域名查詢(xún)成功,則返回的字符串為IP
-
if(!preg_match($pattern, $ip))
//檢測(cè)是否返回IP,若未返回IP,即域名查詢(xún)失敗,報(bào)錯(cuò)
-
{
-
echo 'alert("Invalid Input!"); ';
-
die();
-
}
-
}
-
}
經(jīng)過(guò)以上一系列處理,就可以從參數(shù)中獲取真實(shí)的IP用于查詢(xún)了。
2.通過(guò)IP獲取地理信息
利用MaxMind?取得某IP的地理信息是相對(duì)容易的,查詢(xún)的結(jié)果是一個(gè)結(jié)構(gòu)體,包含國(guó)家代碼、國(guó)家名稱(chēng)、城市名稱(chēng)和城市經(jīng)緯度等信息。下面對(duì)其中元素進(jìn)行一一說(shuō)明。
country_code - 國(guó)家代碼(兩位),如中國(guó)為CN。
country_code3 - 國(guó)家代碼(三位),如中國(guó)為CHN。
country_name - 國(guó)家名稱(chēng)(英文),如中國(guó)為China。
region - 區(qū)域代碼,通過(guò)$GEOIP_REGION_NAME[$record->country_code] [$record->region]可獲得區(qū)域的名稱(chēng)。對(duì)于中國(guó),region得到的是省級(jí)行政區(qū)的名稱(chēng),如$GEOIP_REGION_NAME["CN"]["01"]對(duì)應(yīng)的行政區(qū)即位Anhui(安徽)。
city - 城市名稱(chēng)。
postal_code - 郵編,僅美國(guó)可用。
latitude - 緯度。
longitude - 經(jīng)度。
dma_code - DMA代碼,僅美國(guó)可用。
area_code - 地區(qū)代碼,僅美國(guó)可用。
了解數(shù)據(jù)的組織結(jié)構(gòu)后就可以方便地使用其中的數(shù)據(jù)了。代碼如下:
-
//接上面程序
-
-
//如果取消下一行將使用共享內(nèi)存打開(kāi)GeoLiteCity數(shù)據(jù)庫(kù),
可加快查詢(xún)。但前提是服務(wù)器支持共享內(nèi)存
-
//$gi = geoip_open("./GeoLiteCity.dat",GEOIP_MEMORY_CACHE);
-
-
//以常規(guī)方式打開(kāi)GeoLiteCity數(shù)據(jù)庫(kù),一般情況下都可以使用
-
$gi = geoip_open("./GeoLiteCity.dat",GEOIP_STANDARD);
-
-
//以上是假定GeoLiteCity數(shù)據(jù)庫(kù)和PHP文件在同一個(gè)目錄,
故使用"./GeoLiteCity.dat"為路徑
-
//如果不是,請(qǐng)改為實(shí)際目錄
-
-
//獲取IP的信息
-
$record = geoip_record_by_addr($gi, $ip);
-
//關(guān)閉數(shù)據(jù)庫(kù)
-
geoip_close($gi);
-
-
//如果獲取了相關(guān)數(shù)據(jù)
-
if($record)
-
{
-
echo 'loadGeoInfo('.
-
'"'. $_GET['q'] .'",'.
//原始查詢(xún)信息
-
'"'. $ip .'",'. //被查IP
-
'"'. $record->country_code
.'",'. //國(guó)家代碼(兩位)
-
'"'. $record->country_code3
.'",'. //國(guó)家代碼(三位)
-
'"'. $record->country_name
.'",'. //國(guó)家名稱(chēng)
-
'"'. $GEOIP_REGION_NAME
[$record->country_code] [$record->region] .'",'.
//地區(qū)名稱(chēng)
-
'"'. $record->city .'",'.
//城市名稱(chēng)
-
$record->latitude .','. //緯度
-
$record->longitude .')'; //經(jīng)度
-
//如果數(shù)據(jù)庫(kù)中不存在相關(guān)數(shù)據(jù)
-
else
-
{
-
echo 'alert("The Information for '.$ip.' is not available now!"); ';
-
}
-
?>
將以上代碼整合到一起,保存為search.php,放到本程序的主目錄中(search.php完整代碼在光盤(pán)中本章節(jié)目錄里可以找到)。
在瀏覽器中輸入http://服務(wù)器地址/程序所在路徑/search.php?q=google.com,應(yīng)該會(huì)顯示與下面信息類(lèi)似的輸出結(jié)果。
loadGeoInfo("google.com", "64.233.187.99", "US", "USA", "United States", "California", "Mountain View", 37.4192,-122.0574)
而輸入http://服務(wù)器地址/程序所在路徑/search.php?q=202.114.64.139,則輸出應(yīng)該和下面類(lèi)似。
loadGeoInfo("202.114.64.139", "202.114.64.139", "CN", "CHN", "China", "Hubei", "Wuhan" ,30.5833, 114.2667)