前提
phpとMySQLを使い、「IPアドレスごとの操作履歴」の保存に取り組んでいます。
例えば「どのユーザーがいついいねを押したか」などです。
(非会員でもいいねが可能なのでIPアドレスでの実装を考えました。)
※以下、クエリ生成に変数の直渡しをしておりますが、質問用の簡易コードとしてご理解ください。
実現したいこと
IPアドレスをMySQLに保存する際の適切な処理を知りたいです。
発生している問題
特にカラムとしてVARCHAR
かINT
か決めかねています。
現状の保存処理
現状はphpの$_SERVER
から得た値をVARCHAR(15)
で、次のように保存しています。
SQL
1-- ipアドレスのテーブル 2CREATE TABLE tbl_ips ( `ip` VARCHAR(15) NOT NULL );
php
1$ip = $_SERVER["REMOTE_ADDR"]; 2$sql = "INSERT INTO tbl_ips ( ip ) VALUES ( $ip );"
調べたこと
調べたこと1:INET_ATONが便利っぽい
検索するうちにINET_ATON
の存在を知りました。次のように使うようです。
SQL
1-- ipアドレスのテーブル 2CREATE TABLE tbl_ips ( `ip` INT(10) NOT NULL );
php
1$ip = $_SERVER["REMOTE_ADDR"]; 2$sql = "INSERT INTO tbl_ips ( ip ) VALUES ( INET_ATON( $ip ) );"
どうやらこれを使い数値で管理すると、次のように速度面と安全面のメリットがあると知りました。
>検索速度とか考えると今回の方法を使っていくべき
https://taitan916.info/blog/archives/2549
>パソコンからの成りすましをある程度抑制できます
https://ir.hatakenet.com/archives/91
調べたこと2:INET_ATONだけではダメっぽい
しかしさらに調べると、IPアドレスには ipv4 と ipv6 という種類があるようで、INET_ATON
も ipv6 の場合はINET6_ATON
を使わなければならないという次の記事を見つけました。
>IPv6の場合は、データ型にVARCHAR(16)を指定して、INET6_ATON()とINET6_NTOA()関数を使うようです
http://ajiblog.sblo.jp/article/104930826.html
生じた疑問
そこで疑問なのですが、INET_ATON
とINET6_ATON
の区別が必要というこは、まずphpの段階で次の区別が必要ということになるかと思います。
php
1// ipv4 を判定 2function isIPv4($ip) { 3 return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); 4} 5 6// ipv6 を判定 7function isIPv6($ip) { 8 return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); 9}
そしてこう区別して、さらにテーブルも次のように区別するということになるのでしょうか?
SQL
1-- ipv4 のテーブル 2CREATE TABLE tbl_ipv4s ( `ipv4` INT(10) NOT NULL ); 3 4-- ipv6 のテーブル 5CREATE TABLE tbl_ipv6s ( `ipv6` VARCHAR(16) NOT NULL );
ずいぶん遠回りというか不自然な印象を覚えます。
いったいIPアドレスの管理するテーブル構造とは、どのようなものがよろしいでしょうか?
バージョン
PHP 8.0
MySQL 5.7.31
phpMyAdmin 4.4.15.10
宜しくお願いいたします。
