ip2long / long2ip 基礎用法<?php
$ip = '210.110.11.49';
$int = ip2long($ip); // -764540111 (有號整數)
$unsigned = sprintf('%u', $int); // 3530427185 (無號整數)
echo long2ip($int); // 210.110.11.49
?>
關鍵點:PHP 整數為有號 32 位元,IP 轉換結果可能為負數。資料庫儲存建議使用 UNSIGNED INT 欄位,PHP 端用 sprintf('%u', $int) 或 $int & 0xFFFFFFFF 轉無號值。
ip2long 的隱藏 Bug<?php
// 錯誤示範
$ip = '210.110.011.49'; // 第三段有前導零
echo ip2long($ip); // -764540623
echo long2ip($ip); // 210.110.9.49 ← 錯誤!解析為八進位
$ip = '021.110.11.49'; // 第一段有前導零
echo ip2long($ip); // 292424497
echo long2ip($ip); // 17.110.11.49 ← 錯誤!
?>
原因:PHP 將帶前導零的數字字串視為八進位。011 → 九進位 9,021 → 八進位 17。
<?php
function cleanIp($ip) {
return implode('.', array_map('intval', explode('.', $ip)));
}
$ip = cleanIp('210.110.011.49'); // 210.110.11.49
echo ip2long($ip); // 正確
?>
<?php
function ipToInt($ip) {
$seg = explode('.', $ip);
return (intval($seg[0]) << 24)
| (intval($seg[1]) << 16)
| (intval($seg[2]) << 8)
| intval($seg[3]);
}
function intToIp($int) {
return ($int >> 24 & 255) . '.'
. ($int >> 16 & 255) . '.'
. ($int >> 8 & 255) . '.'
. ($int & 255);
}
?>
<?php
function ipToInt($ip) {
$seg = explode('.', $ip);
$num = 0;
foreach ($seg as $i => $v) {
$num += intval($v) * pow(256, 3 - $i);
}
return $num;
}
?>
<?php
// 方法一:手動檢查各段範圍
function checkIp($ip) {
$seg = explode('.', $ip);
if (count($seg) !== 4) return false;
foreach ($seg as $v) {
if (!ctype_digit($v) || $v > 255) return false;
}
return true;
}
// 方法二:利用 ip2long 特性 (需先 cleanIp)
function checkIp2($ip) {
$ip = cleanIp($ip);
return ip2long($ip) !== false;
}
?>
INT UNSIGNED NOT NULL$int = sprintf('%u', ip2long(cleanIp($ip)))long2ip($int) 直接還原WHERE ip_int BETWEEN start AND end 極高效能