Я хочу хранить IP-адреса в своей базе данных, но мне также нужно использовать их во всем приложении. Я прочитал об использовании INET_ATON()
и INET_NTOA()
в моих MySQL-запросах, чтобы получить 32-разрядное целое число без знака из IP-адреса, что именно то, что я хочу, так как это сделает поиск по базе данных быстрее, чем использование char (15) ,
Дело в том, что я не могу найти функцию, которая делает то же самое в PHP. Единственное, с чем я столкнулся, это:
http://php.net/manual/en/function.ip2long.php
Поэтому я протестировал его:
$ip = $_SERVER['REMOTE_ADDR']; echo ip2long($ip);
И он ничего не выводит. В примере, который они дали, похоже, он работает, но опять же я не совсем уверен, что ip2long()
делает то же самое, что и INET_ATON()
.
Кто-нибудь знает функцию PHP, которая сделает это? Или даже совершенно новое решение для хранения IP-адреса в базе данных?
Благодарю.
Функции ip2long()
и long2ip()
должны работать нормально.
Примечание: вы должны использовать их для IPv4-адресов – убедитесь, что в вашем случае $_SERVER['REMOTE_ADDR']
действительно содержит действительный IPv4-адрес (а не некоторые вещи IPv6) .
Попытка использования IP-адреса google:
var_dump(ip2long('209.85.227.147')); var_dump(long2ip(3512066963));
Я получаю следующий вывод:
int(3512066963) string(14) "209.85.227.147"
Существует важное различие между функциями ip2long, long2ip и MySQL.
PHP ip2long и long2ip заключают сделки со значащими целыми числами.
См. http://php.net/manual/en/function.ip2long.php
«Поскольку целочисленный тип PHP подписан, а многие IP-адреса приведут к отрицательным целым числам на 32-разрядных архитектурах, вам нужно использовать форматирование '% u' из sprintf () или printf (), чтобы получить строковое представление неподписанного IP-адреса адрес."
В INET_ATON () и INET_NTOA () MySQL используются целые числа без знака
См. http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_inet-aton
«Чтобы хранить значения, созданные INET_ATON (), используйте столбец INT UNSIGNED, а не INT, который подписан. Если вы используете столбец с подписью, значения, соответствующие IP-адресам, для которых первый октет больше 127, нельзя сохранить правильно».
Вот некоторые функции, которые вы можете использовать для работы между ними.
Если вы вставили в базу данных MySQL, IP используя INET_ATON (), вы можете преобразовать ее обратно в PHP, используя следующее:
long2ip(sprintf("%d", $ip_address));
И вы можете преобразовать его, чтобы сохранить его в базе данных из PHP, используя это:
sprintf("%u", ip2long($ip_address));
(Также важно не вводить тип $ ip_address в int, так как это может вызвать проблемы, обертывая число, если оно больше MAX_INT. Если вы должны его отбросить, добавьте его в длинный или плавающий)
Вы не должны иметь дело с тем, что внутри 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 | +----------+------------------+
Если вы хотите иметь дело с 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 | +--------------------------+---------------------------------+
Вы можете видеть, что, делая это, вы фактически можете избежать оценки адресов ipv6 в разных форматах, поскольку MySQL преобразует их в двоичные и обратно в их простое выражение.
Я знаю, что этот вопрос уже более двух лет, но я хочу, чтобы эта информация была полезной для других, которые сталкиваются.
НТН
Франсиско Зарабозо
Для поддержки IPv4 и IPv6 используйте inet_pton()
и inet_ntop()
, они доступны с PHP 5.1+ и точно имитируют эквивалентные функции MySQL.
В противном случае просто используйте ip2long()
и long2ip()
.
Здесь PHP альтернативные функции (простая копия / вставка в вашей программе) –
function inet_aton($ip) { $ip = trim($ip); if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) return 0; return sprintf("%u", ip2long($ip)); } function inet_ntoa($num) { $num = trim($num); if ($num == "0") return "0.0.0.0"; return long2ip(-(4294967295 - ($num - 1))); }
ip2long эквивалентно inet_aton ().
ip2long работает только с IPv4. Я подозреваю, что ваша система использует IPv6 для loopback. Попробуйте распечатать REMOTE_ADDR.