地理定位查詢主要可分為兩個步驟:第一,獲取待查詢的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)