在使用PHP将IP地址存储到MySQL数据库中,不需要解释。

60

在MySQL中,IP地址的正确字段类型是什么?使用PHP存储的正确方法是什么?


1
这可能会对你有所帮助:https://dev59.com/iHNA5IYBdhLWcg3wPbSe? - Alfred
我只想在注册后存储用户的IP。如果发生什么事情,我需要用户的IP;我会查看。 - user552828
1
在这种情况下,请使用VARCHAR(39),以便您可以存储所有版本的IP。 - Sander
1
我关心IPv4和IPv6两者。 - user552828
1
@user552828,@Sander - 在VARCHAR字段中保存IP地址非常低效。请看一下我的答案。 - Francois Deschenes
显示剩余2条评论
3个回答

62

这个教程 可能会对您有所帮助。

最有效的保存 IPv4 地址的方法是使用 INT 字段(而不是您可能预期的 VARCHAR)。您可以使用 PHP 的 ip2long 函数进行转换,并使用 MySQL 的INET_NTOA 函数或 PHP 的 long2ip 函数进行还原。

如果需要存储 IPv6,则应使用 BINARY 字段,以及 PHP 的 inet_pton 函数。


没有名为ip2bin的内置函数。不过你可以很容易地自己编写一个:function ip2bin($ip) { return inet_pton($ip); } - knittl
@knittl - 我添加了我所提到的函数。我的错,没有包含它。 - Francois Deschenes
4
为什么不直接使用inet_pton?它已经可以处理几乎所有IP地址的字符串表示形式,无需进行复杂的转换。 - knittl
@knittl - 这是一个很好的观点。让我更新我的答案。 - Francois Deschenes
1
如果您正在运行64位系统,则MySQL INT字段必须是UNSIGNED。 - JoshuaDavid
即使您运行的是32位系统,计算时也会将其视为BIGINT UNSIGNED。对于IPv6地址,请使用INET6_ATON()和INET6_NTOA()函数以及HEX()和UNHEX()函数将IP地址存储为BINARY列。但数据类型取决于您想要对此数据执行什么操作。请在此处查看http://www.rathishkumar.in/2017/08/how-to-store-ip-address-in-mysql.html。 - Rathish Kumar B

53

你可以将IP地址存储在长度为128位(16字节)的二进制字段中,使用BINARY(16)VARBINARY(16)

要将任何IP地址转换为其二进制表示形式,可以使用PHP函数inet_pton。此方法适用于IPv4和IPv6地址。 inet_ntop可用于获取存储的IP地址的字符串表示形式(无论版本如何)。


我可以同时用于IPv6和IPv4吗? - user552828
2
@user552828:是的,你可以同时用于IPv4和IPv6。 - knittl
但是他们说,在隧道IP的情况下,IPv6可以达到45个字符长,那么128位长度是否可以呢?我问这个问题是因为我不太擅长编程,我是新手。 - user552828
IPv6地址长度始终为128位。不同的字符串表示可以给出不同的字符串长度。对于隧道IPv6地址,它可能看起来像这样:1234:4567:89ab:cdef:1234:ffff:127.127.127.127(不完全正确,通常是::ffff:127.127.127.127(80位零,16位一,32位IPv4地址))。 - knittl
8
pton表示将“表现形式”转换为“网络形式”,ntop表示将“网络形式”转换为“表现形式”。 - Bell
2
@knittl 看起来在这种情况下使用 BINARY(16) 不太合适。请查看此链接:https://dev59.com/j1MI5IYBdhLWcg3wyunE,应改用 VARBINARY(16) - Vladimir

17

通常情况下,您可以选择使用VARCHAR(45),因为它足够长,甚至可以存储IPv6。


7
如果您使用隧道地址,IPv6地址可能会达到45个字符。虽然这是边缘情况,但为什么不考虑未来的需求呢? - Robert
哦,是的,忘了那个 :) - Sander
5
所以,基本上你会为使用最大16字节的地址使用多达45个字节?在我看来这似乎很浪费...(对于IPv4地址情况更糟:4字节地址和15字节的字符串表示形式。) - knittl
1
@Knittl,你不应该在VARCHAR中使用空数据,这只适用于CHAR,请参考:http://dev.mysql.com/doc/refman/5.0/en/char.html。 - Sander
3
是的,这就是为什么我写“IPv4地址需要15字节”,而不是45字节。它仍然使用了比必要的多近4倍的空间。 - knittl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接