ble*_*erh 33 php mysql sql database ip-address
我想在我的数据库中存储IP地址,但我还需要在整个应用程序中使用它们.我读到了使用INET_ATON()和INET_NTOA()在我的MySQL查询中从IP地址中获取32位无符号整数,这正是我想要的,因为它将比使用char(15)更快地搜索数据库.
问题是,我找不到一个在PHP中做同样事情的函数.我遇到的唯一一件事是:
http://php.net/manual/en/function.ip2long.php
所以我测试了它:
$ip = $_SERVER['REMOTE_ADDR'];
echo ip2long($ip);
Run Code Online (Sandbox Code Playgroud)
它什么也没输出.在他们给它的例子似乎工作,但再次我不确定是否ip2long()做同样的事情INET_ATON().
有人知道这样做的PHP函数吗?甚至是在数据库中存储IP地址的全新解决方案?
谢谢.
Pas*_*TIN 36
注意:您应该将这些用于IPv4地址 - 在您的情况下,请确保$_SERVER['REMOTE_ADDR']实际包含有效的IPv4地址(而不是某些IPv6内容).
尝试使用Google IP地址:
var_dump(ip2long('209.85.227.147'));
var_dump(long2ip(3512066963));
Run Code Online (Sandbox Code Playgroud)
我得到以下输出:
int(3512066963)
string(14) "209.85.227.147"
Run Code Online (Sandbox Code Playgroud)
Tom*_*Tom 31
有一个重要区别ip2long,long2ip和MySQL的功能.
PHP ip2long和long2ip处理有符号整数.
见http://php.net/manual/en/function.ip2long.php
"因为PHP的整数类型已签名,并且许多IP地址将在32位体系结构上产生负整数,所以需要使用sprintf()或printf()的'%u'格式化程序来获取无符号IP的字符串表示形式地址."
MySQL INET_ATON()和INET_NTOA()处理无符号整数
请参阅http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_inet-aton
"要存储由INET_ATON()生成的值,请使用INT UNSIGNED列而不是INT(已签名).如果使用带符号列,则无法正确存储与第一个八位字节大于127的IP地址对应的值."
以下是一些可用于在两者之间工作的函数.
如果你插入MySQL数据库,使用IP INET_ATON(),你可以使用以下代码在PHP中将其转换回来:
long2ip(sprintf("%d", $ip_address));
Run Code Online (Sandbox Code Playgroud)
您可以将其转换为使用以下方法将其保存在PHP数据库中:
sprintf("%u", ip2long($ip_address));
Run Code Online (Sandbox Code Playgroud)
(同样重要的是,不要对其进行类型$ip_address转换,int因为这可能会导致问题,如果它的数量大于包装数字MAX_INT.如果你必须强制转换它,将其转换为long或者float)
Fra*_*ozo 17
您不应该在PHP内部处理,这就是MySQL本机功能所针对的.看这个例子:
create table iptable (
ip int(32) unsigned not null,
comment varchar(32) not null
);
insert into iptable (ip, comment) values (inet_aton('10.0.0.3'), 'This is 10.0.0.3');
select * from iptable;
+-----------+------------------+
| ip | comment |
+-----------+------------------+
| 167772163 | This is 10.0.0.3 |
+-----------+------------------+
select inet_ntoa(ip) as ip, comment from iptable;
+----------+------------------+
| ip | comment |
+----------+------------------+
| 10.0.0.3 | This is 10.0.0.3 |
+----------+------------------+
Run Code Online (Sandbox Code Playgroud)
如果你想在同一个字段中处理ipv4和ipv6,并且你使用的是Mysql 5.6或更高版本,你可以使用varbinary(16)和函数inet6_aton和inet6_ntoa.这是一个更好的例子,说明为什么你应该使用MySQL函数而不是处理PHP中的二进制数据:
create table iptable2 (
ip varbinary(16) not null,
comment varchar(32) not null
);
insert into iptable2 (ip, comment) values
(inet6_aton('192.168.1.254'), 'This is router 192.168.1.254'),
(inet6_aton('::1'), 'This is ipv6 localhost ::1'),
(inet6_aton('FE80:0000:0000:0000:0202:B3FF:FE1E:8329'), 'This is some large ipv6 example')
;
select * from iptable2;
+------------------+---------------------------------+
| ip | comment |
+------------------+---------------------------------+
| +¿?¦ | This is router 192.168.1.254 |
| ? | This is ipv6 localhost ::1 |
| ¦Ç ??¦ ¦?â) | This is some large ipv6 example |
+------------------+---------------------------------+
select inet6_ntoa(ip) as ip, comment from iptable2;
+--------------------------+---------------------------------+
| ip | comment |
+--------------------------+---------------------------------+
| 192.168.1.254 | This is router 192.168.1.254 |
| ::1 | This is ipv6 localhost ::1 |
| fe80::202:b3ff:fe1e:8329 | This is some large ipv6 example |
+--------------------------+---------------------------------+
Run Code Online (Sandbox Code Playgroud)
您可以看到,通过这样做,您实际上可以避免必须以不同格式评估ipv6地址,因为MySQL将它们转换为二进制并返回到最简单的表达式.
我知道这个问题已经有两年多了,但我想让这些信息对遇到的其他人有用.
HTH
Francisco Zarabozo
Ali*_*xel 11
对于IPv4和IPv6支持使用inet_pton()和inet_ntop(),这是因为PHP availiable 5.1+和模仿完全等价的MySQL功能.
否则只需使用ip2long()和long2ip().
| 归档时间: |
|
| 查看次数: |
48228 次 |
| 最近记录: |