INET_ATON () и INET_NTOA () в PHP?

Я хочу хранить 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.