PHPでGeolite2ライブラリを使って、IPアドレスから地域情報を取得する方法について記載します。
コンソール上でのGeoLite2の実行結果

環境
 Windows11 Home
 PHP 8.3.8 & composer 2.7.7
手順
①MaxmindからIPのデータベース情報を取得
 ・Maxmindアカウントの作成(無料ユーザ登録)
 ・データベース情報のダウンロード
②GeoLite2を使ってIPから地域情報を取得
 ・DBの保存形式を確認
 ・Composerを使ってGeolite2をインストール
   (インストールがうまくいかない場合)
 ・GeoLite2を使ってIPアドレスから地域情報を取得
データベース情報を取得
Maxmindの公式ページは次のリンクからジャンプできます。
   https://www.maxmind.com/en/geoip-databases
   表示すると、自身の地域情報が表示されます。
    国名だけでなく、都市名、GPS情報(多分サーバの位置かなと思います)、郵便番号も表示されています。
①Maxmindアカウントの作成
 データベース情報をダウンロードするためには、無料のアカウント登録が必要です。
 有料アカウントもありますが、精度がよくなるだけであり、ダウンロード制限もないので、私は無料アカウントでで充分です。
 ユーザ登録ページ GeoLite2 Sign Up | MaxMind
 ●ユーザ情報登録ページ

 入力項目(全部必須入力のようです) 
  名前 会社 業界  国  
  使用目的 不正の検知目的とかウェブの分析といったところでしょうか
  メールアドレス 有効なメールアドレスが必要です
  電話番号 必須ではありません
  Maxmindデータをどのように使用するか プラットフォームやソフトウェア、Web等
  データをどのように活用するか 統計資料や不正検知、ウェブの分析等
 送られてきたメールを使ってパスワードを設定すればアカウントを作成することができます。
 ログインは初期設定で二段階認証になっており、ログインするたびにメールにpinコードが送られてきます。(いいね)
②データベース情報のダウンロード
 ログイン後、画面の左にあるメニューバーから
   GeoIP2/GeoLite2
を選択するとダウンロード画面が開きます。
 圧縮されているので、解凍して実行ファイルと同じフォルダにコピーしておきます。
●ダウンロード画面

ダウンロードできるデータベースは次の通りです。
| データベース | 説明 | 
| GeoLite2 ASN | IPアドレスとASNの対応表(6MB程度) (CVS 6MB程度、MMDB 3MB程度 )  | 
| GeoLite2 City | IPアドレスと都市名の対応表(145MB程度) (CVS 150MB程度、MMDB 60MB程度 )  | 
| GeoLite2 Country | IPアドレスと国名の対応表(4MB程度) (CVS 4MB程度、MMDB 3MB程度 )  | 
 都市名と国名は英語だけでなく、日本語で書かれたものもあり、かなり親切設計でした。
 フォーマットの種類は次の2種類で提供されています。
   csv形式 他のソフトウェアでDBを利用したい場合、読込が遅い
   mmdb形式 mindmax社独自のDB形式、読込が早い
 データの中身を確認したり、独自で読込ソフトウェアを作成するのならcsvでダウンロードする必要があります。
 今回は、GeoLite2 Cityのcsvとmmdbの両方をダウンロードしました。
GeoLite2を使ってIPから地域情報を取得
取得したDB情報を使って地域情報を取得します。
①DBの保存形式を確認
 GeoLite2 City CSV ファイルをダウンロードしたところ、次のファイル等が含まれていました。
| ファイル名 | |
| GeoLite2-City-Blocks-IPv4.csv | ipv4アドレスとgeoname_idの対応表 等 | 
| GeoLite2-City-Blocks-IPv6.csv | ipv6アドレスとgeoname_idの対応表 等 | 
| GeoLite2-City-Locations-ja.csv | geoname_idと、都市名、国名の対応表 等 | 
指定されたIPアドレスを一度geoname_idに変換してから、geoname_idを使って都市名を取得するという流れですね。
 mmdbファイルはバイナリ化されており、内容を可読化することはできません。
②Composerを使ってGeoLite2をインストール
・GeoLite2のインストールが失敗
 次のコマンドでGeoLite2をインストールしたところ、警告が表示されて失敗しました。
c:\{インストールDIR} >composer require geoip2/geoip2
./composer.json has been created
Running composer update geoip2/geoip2
Loading composer repositories with package information
:
    - guzzle/guzzle[v3.0.0, ..., v3.9.3] require ext-curl * -> it is missing from your system. Install or enable PHP's curl extension.
    - maxmind/web-service-common[v0.0.2, ..., v0.9.0] require ext-curl * -> it is missing from your system. Install or enable PHP's curl extension.
To enable extensions, verify that they are enabled in your .ini files:
    - C:\{PHP_HOME}\php.ini
You can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode.
Alternatively, you can run Composer with `--ignore-platform-req=ext-curl` to temporarily ignore these required extensions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require geoip2/geoip2:*" to figure out if any version is installable, or "composer require geoip2/geoip2:^2.1" if you know which you need.
Installation failed, deleting ./composer.json.当環境では、php.ini 内でcurlが使用できなくなっているというエラーが発生しましたので、警告に従って、
  C:\{PHP_HOME}\php.ini
を開いて
次のコメントを解除
;extension=curl
↓
extension=curlとしたところ、同じコマンドでインストールが成功しました。
③GeoLite2を使ってIPアドレスから地域情報を取得
 composerでGeolite2をインストールしたフォルダで次のPHPプログラムを作成しました。
<?php 
require './vendor/autoload.php';
use GeoIp2\Database\Reader;
use GeoIp2\Exception\AddressNotFoundException;
try {
    # ダウンロードしたバイナリを指定
    $my_reader = new Reader('./GeoLite2-City.mmdb');
    # チェックしたいIPアドレスを指定
    $ip = "61.120.205.110"; # とりあえず東京都のHPのIPを入力
    $res = $my_reader->city($ip);
    # IPを表示
    var_dump("IPアドレス: $ip");
    
    # 国コード
    $isocode = $res->country->isoCode;
    var_dump("国コード(isoCode):$isocode");
    
    # 国名
    $name = $res->country->name;
    var_dump("国名(country name):$name");
    
    # 国名 names['ja']が存在するかをチェックして表示
    if (isset($res->country->names['ja'])) {
        $name_ja = $res->country->names['ja'];
        var_dump("国名(country name ja):$name_ja"); # 国名(日本語)
    } else {
        echo "日本語の国名情報がありません。";
    }
    # 都市名(日本語)が存在するかをチェックして表示
    if (isset($res->city->names['ja'])) {
        $city_ja = $res->city->names['ja'];
        var_dump("都市名(city name ja):$city_ja"); # 都市名(日本語)
    } else {
        echo "日本語の都市名情報がありません。";
    }
} catch (AddressNotFoundException $e) {
    # 結果が見つからない場合の処理
    echo "データベースに結果が見つかりませんでした。";
    
} catch (Exception $e) {
    # その他のエラーをキャッチ
    echo "エラーが発生しました: " . $e->getMessage();
}
?>フォルダ構成は次の通り
c:\{実行フォルダ}
 ├― vendor (composerによって作成されたフォルダ)
 |   ├― autoload.php (Geoip ロードファイル)
 |   :  省略
 ├― composer.json(composerによって作成された定義ファイル)
 ├― composer.lock(composerによって作成された定義ファイル)
 ├― test.php (今回作成したphp実行ファイル)
 ├― GeoLite2-City.mmdb (ダウンロードしたDBファイル)
 ├― GeoLite2-City-Blocks-IPv4.csv (ダウンロードしたDBファイル なくても実行可)
 ├― GeoLite2-City-Locations-ja.csv (ダウンロードしたDBファイル なくても実行可)
実行結果は次の通りです。
C:\{実行フォルダ}>php test.php
string(30) "IPアドレス: 61.120.205.110"
string(24) "国コード(isoCode):JP"
string(26) "国名(country name):Japan"
string(30) "国名(country name ja):日本"
string(30) "都市名(city name ja):東京" IPアドレスは東京都のHPのものを入力しました。
 IPによっては、「●●区」「●●町」まで表示されます。
 ちなみに、自身のIPアドレスを入力したところ、正確な都市名が表示されました。
 GeoLite2は、ja表記が無い都市名を表示しようとするとExceptionを吐いてくるので、try~catchで囲んでおく必要があります。
最後に
 Geolite2を使ってIPアドレスから地域情報を取得することができました。
 GoogleAnalize等で利用者の都市名が表示されるのは、こういう仕組みを利用しているのですね。
 Maxmind社がどのようにしてIPの地域情報を集めているのかはわかりませんが、これだけの情報を無料で使わせてくれることに感謝です。
 GeoIPのライセンスを読むと、「MaxMindはサービスを無料で提供していますが、将来的に有料にする権利を保持します。」等と書かれていたので、無料のうちに使って経験を積んだほうがいいと感じています。

