使 PHP 中 ip2long 方法支持 IPv6

编程 暂无评论

在很多项目中需要将 IP 地址存储于数据库中,因地址格式复杂,存储可能导致出现格式等兼容性问题,因此一般都会对地址进行处理。在 PHP 中一般使用 ip2long 函数将地址转换为一个长数组,但是需要注意的是此函数目前仅仅支持 IPv4 类的地址。

在谷歌中搜索后发现在 PHP 官网中存在一个大佬的解决方案

Here some working ip2long6 and long2ip6 functions - keep in mind that this needs php gmp-lib.
这是一个可以使用的 IPv6 转换方法 - 需要注意的是此方法需要使用 PHP 的 gmp-lib 库/扩展。

此为试验的 Demo 。

<?php

$ipv6 = "2001:4860:a005::68";

function ip2long6($ipv6) {
  $ip_n = inet_pton($ipv6);
  $bits = 15; // 16 x 8 bit = 128bit
  while ($bits >= 0) {
    $bin = sprintf("%08b",(ord($ip_n[$bits])));
    $ipv6long = $bin.$ipv6long;
    $bits--;
  }
  return gmp_strval(gmp_init($ipv6long,2),10);
}

function long2ip6($ipv6long) {

  $bin = gmp_strval(gmp_init($ipv6long,10),2);
  if (strlen($bin) < 128) {
    $pad = 128 - strlen($bin);
    for ($i = 1; $i <= $pad; $i++) {
    $bin = "0".$bin;
    }
  }
  $bits = 0;
  while ($bits <= 7) {
    $bin_part = substr($bin,($bits*16),16);
    $ipv6 .= dechex(bindec($bin_part)).":";
    $bits++;
  }
  // compress

  return inet_ntop(inet_pton(substr($ipv6,0,-1)));
}

print $ipv6long =  ip2long6($ipv6)."\n";
print $ipv6 = long2ip6($ipv6long)."\n";

?>

outputs:

42541956150894553250710573749450571880
2001:4860:a005::68

注意:因 IPv6 地址转换后的字符串长度增加,因此可能需要调整数据库的字段长度(38位)。

实际上此函数的使用是因为魔改大佬的 Access 项目所用到的,这是 @kokororin 大佬的作品,在此基础上进行了一系列改动:

更多使用说明及特性请转至 GitHub 查看

小贴士:因此改动较大,因此若尝试这些新特性请使用 mainline 分支, master 分支为小修改分支。

附录

参考链接

如果遇到问题或者对文章内容存疑,请在下方留言,博主看到后将及时回复,谢谢!
回复
回答41+28=