データベースにIPアドレスを保存したいのですが、アプリケーション全体で使用する必要があります。 MySQLクエリでINET_ATON()
およびINET_NTOA()
を使用してIPアドレスから32ビット符号なし整数を取得する方法について読みました。これは、 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
_と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ではなくINT UNSIGNED列を使用します。署名された列を使用すると、最初のオクテットが127より大きいIPアドレスに対応する値を正しく格納できません。」
ここで、2つの間で作業するために使用できる関数をいくつか示します。
INET_ATON()
を使用してIPであるMySQLデータベースに挿入した場合、次を使用してPHPに戻すことができます。
_long2ip(sprintf("%d", $ip_address));
_
そして、これを変換してPHPからデータベースに保存することができます:
_sprintf("%u", ip2long($ip_address));
_
(また、_$ip_address
_をint
に型キャストしないでください。これは、_MAX_INT
_より大きい場合、数値をラップすることで問題を引き起こす可能性があります。キャストする必要がある場合は、キャストしてください。 long
またはfloat
へ)
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 |
+--------------------------+---------------------------------+
これを行うことで、MySQLが異なる形式のipv6アドレスを評価する必要を実際に回避できることがわかります。MySQLはそれらをバイナリに変換し、最も単純な式に戻すからです。
この質問にはすでに2年以上かかっていることは知っていますが、この情報が他の人に役立つようにしたいと思います。
HTH
フランシスコ・ザラボゾ
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を使用していると思われます。 REMOTE_ADDRを印刷してみてください。