在反向代理、CDN、負載均衡等架構下,$_SERVER['REMOTE_ADDR'] 往往只能拿到代理伺服器 IP。本文提供一個健全的 getIP() 函數,支援多層代理標頭判斷,並整合淘寶免費 IP 定位 API(HTTP 介面,無需本地資料庫),即時取得國家、省份、城市、ISP 等資訊。
function getIP() {
static $realip;
if (isset($_SERVER)) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// 可能包含多個 IP,取第一個非私有 IP
$proxies = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
foreach ($proxies as $ip) {
$ip = trim($ip);
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) continue;
$realip = $ip;
break;
}
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$realip = $_SERVER['HTTP_CLIENT_IP'];
} else {
$realip = $_SERVER['REMOTE_ADDR'];
}
} else {
// 老式 CGI 環境 fallback
$realip = getenv('HTTP_X_FORWARDED_FOR') ?: getenv('HTTP_CLIENT_IP') ?: getenv('REMOTE_ADDR');
}
return $realip ?: '0.0.0.0';
}
介面:https://ip.taobao.com/service/getIpInfo.php?ip=IP,回傳 JSON,欄位包含 country、region、city、isp、area_id 等。
function getCity($ip) {
$url = 'https://ip.taobao.com/service/getIpInfo.php?ip=' . urlencode($ip);
$json = @file_get_contents($url);
if (!$json) return false;
$data = json_decode($json, true);
if (($data['code'] ?? 1) != 0) return false; // code=0 成功
return $data['data'] ?? false; // 回傳關聯陣列
}
// 使用範例
$ip = getIP();
$loc = getCity($ip);
if ($loc) {
echo "{$loc['country']} {$loc['region']} {$loc['city']} {$loc['isp']}";
// 輸出:中國 廣東 廣州 電信
} else {
echo '無法解析位置';
}
https://ip.taobao.com/,建議改用 HTTPS 避免劫持。getIP() 已過濾。file_get_contents 失敗時回傳 false,配合 @ 抑制警告,生產環境建議改用 cURL 並設定超時。function getCityCurl($ip) {
$url = 'https://ip.taobao.com/service/getIpInfo.php?ip=' . urlencode($ip);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 2,
CURLOPT_SSL_VERIFYPEER => false, // 若憑證驗證失敗可關閉
]);
$json = curl_exec($ch);
curl_close($ch);
if (!$json) return false;
$data = json_decode($json, true);
return ($data['code'] ?? 1) == 0 ? $data['data'] : false;
}