web-dev-qa-db-fra.com

INET_ATON () et INET_NTOA () en PHP?

Je souhaite stocker des adresses IP dans ma base de données, mais je dois également les utiliser tout au long de mon application. J'ai lu comment utiliser INET_ATON() et INET_NTOA() dans mes requêtes MySQL pour obtenir un entier non signé 32 bits d'une adresse IP, ce qui est exactement ce que je veux car cela rendra la recherche dans le base de données plus rapide que l'utilisation de char (15).

Le truc c'est que je ne trouve pas une fonction qui fait le même genre de chose en PHP. La seule chose que j'ai rencontrée est:

http://php.net/manual/en/function.ip2long.php

Je l'ai donc testé:

$ip = $_SERVER['REMOTE_ADDR'];
echo ip2long($ip);

Et cela ne produit rien. Dans l'exemple qu'ils ont donné, cela semble fonctionner, mais là encore, je ne sais pas exactement si ip2long() fait la même chose que INET_ATON().

Quelqu'un connaît-il une fonction PHP qui fera cela? Ou même une toute nouvelle solution pour stocker une adresse IP dans une base de données?

Merci.

32
blerh

La fonction ip2long() et long2ip() les fonctions devraient fonctionner très bien.

Remarque: vous devez les utiliser pour les adresses IPv4 - assurez-vous que, dans votre cas, $_SERVER['REMOTE_ADDR'] contient en fait une adresse IPv4 valide (et pas quelques trucs IPv6).


Essayer une adresse IP Google:

var_dump(ip2long('209.85.227.147'));
var_dump(long2ip(3512066963));

J'obtiens la sortie suivante:

int(3512066963)
string(14) "209.85.227.147" 
35
Pascal MARTIN

Il existe une distinction importante entre ip2long, long2ip Et les fonctions MySQL.

ip2long Et long2ip De PHP traitent les entiers signés.

Voir http://php.net/manual/en/function.ip2long.php

"Parce que le type entier de PHP est signé et que de nombreuses adresses IP se traduiront par des nombres entiers négatifs sur les architectures 32 bits, vous devez utiliser le formateur '% u' de sprintf () ou printf () pour obtenir la représentation sous forme de chaîne de l'adresse IP non signée. adresse."

INET_ATON() et INET_NTOA() de MySQL traitent les entiers non signés

Voir http://dev.mysql.com/doc/refman/5.0/en/miscundry-functions.html#function_inet-aton

"Pour stocker les valeurs générées par INET_ATON (), utilisez une colonne INT UNSIGNED plutôt que INT, qui est signé. Si vous utilisez une colonne signée, les valeurs correspondant aux adresses IP pour lesquelles le premier octet est supérieur à 127 ne peuvent pas être stockées correctement."

Voici quelques fonctions que vous pouvez utiliser pour travailler entre les deux.

Si vous avez inséré dans la base de données MySQL, une IP utilisant INET_ATON(), vous pouvez la reconvertir en PHP en utilisant ce qui suit:

long2ip(sprintf("%d", $ip_address));

Et vous pouvez le convertir pour l'enregistrer dans la base de données de PHP en utilisant ceci:

sprintf("%u", ip2long($ip_address));

(Il est également important de ne pas transtyper le $ip_address En int car cela pourrait causer des problèmes en encapsulant le nombre s'il est supérieur à MAX_INT. Si vous devez le convertir, convertissez-le en long ou float)

31
Tom

Vous ne devriez pas avoir à gérer cela à l'intérieur de PHP, c'est à cela que servent les fonctions natives de MySQL. Voir cet exemple:

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 |
+----------+------------------+

Si vous souhaitez traiter à la fois ipv4 et ipv6 dans le même champ et que vous utilisez Mysql 5.6 ou supérieur, vous pouvez utiliser varbinary (16) et les fonctions inet6_aton et inet6_ntoa. C'est un meilleur exemple de la raison pour laquelle vous devriez utiliser les fonctions MySQL et ne pas traiter les données binaires à l'intérieur de 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 |
+--------------------------+---------------------------------+

Vous pouvez voir qu'en faisant cela, vous pouvez réellement éviter d'avoir à évaluer les adresses ipv6 dans différents formats, car MySQL les convertit en binaire et revient à leur expression la plus simple.

Je sais que cette question a déjà plus de 2 ans, mais je veux que ces informations soient utiles pour d'autres qui viennent.

HTH

Francisco Zarabozo

17
Francisco Zarabozo

Pour la prise en charge IPv4 et IPv6, utilisez inet_pton() et inet_ntop() , ceux-ci sont disponibles depuis PHP 5.1+ et imitez exactement les fonctions MySQL équivalentes.

Sinon, utilisez simplement ip2long() et long2ip().

11
Alix Axel

Ici PHP fonctions alternatives (simple copier/coller dans votre programme) -

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))); 
}
3
user2253362

ip2long est équivalent à inet_aton ().

ip2long ne fonctionne qu'avec IPv4. Je soupçonne que votre système utilise IPv6 pour le bouclage. Essayez d'imprimer REMOTE_ADDR.

1
ZZ Coder