直接执行 composer require maxmind-db/reader 即可安装maxmind官方维护的轻量php读取器库,它专用于解析.mmdb文件,不依赖geoip2封装;需用绝对路径加载数据库,复用reader实例以避免重复mmap开销。

直接执行 composer require maxmind-db/reader 就够了
MaxMind 官方维护的 PHP 读取器库已经迁移到 maxmind-db/reader,不是旧版的 geoip2/geoip2(后者依赖前者,但多一层封装)。如果你只需要解析 .mmdb 文件、不依赖 GeoIP2 的模型类或 Web 服务客户端,装这个轻量包最干净。
常见错误是搜到过时教程,尝试装 geoip2/geoip2 或手动下载 .mmdb 后自己写二进制解析——完全没必要。Composer 会自动拉取最新稳定版(目前 v1.13+),并处理好 ext-bcmath 和 ext-json 的运行时依赖检查。
- 执行前确认 PHP 版本 ≥ 7.4(v1.13 起最低要求)
- 如果项目禁用 packagist.org,需在
composer.json中显式配置仓库源:"https://packagist.org" - 安装后不会自动下载 .mmdb 文件——那是你自己的数据资产,得单独获取(比如从 GeoLite2 Free 下载
GeoLite2-City.mmdb)
加载 .mmdb 文件时必须用绝对路径,相对路径会静默失败
MaxMind\Db\Reader\Reader 构造函数只接受文件系统路径,不支持 URL、phar 或流包装器(如 php://memory)。传入相对路径(如 "data/GeoLite2-City.mmdb")在 CLI 下可能工作,但在 Web 环境中因 getcwd() 不一致,大概率抛出 MaxMind\Db\Reader\InvalidDatabaseException,错误信息却是 “Could not open database file”,容易误判为权限问题。
- 始终用
__DIR__ . '/data/GeoLite2-City.mmdb'或realpath(__DIR__ . '/../storage/GeoLite2-City.mmdb') - 加载前建议加一层存在性与可读性校验:
is_readable($path) && filesize($path) > 0 - 不要把 .mmdb 放进
vendor/目录——Composer 可能清理它,也不符合“数据与代码分离”原则
查 IP 时注意 IPv4 映射到 IPv6 的陷阱
IPv4 地址在 .mmdb 中默认以 IPv6 形式存储(如 192.168.1.1 存为 ::ffff:192.168.1.1)。Reader::get() 方法内部会自动做这种映射,但前提是传入的 IP 字符串格式正确:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 传
"192.168.1.1"✅ 自动转为 IPv6 格式再查 - 传
"::ffff:192.168.1.1"✅ 直接查 - 传
"192.168.1.1/32"❌ 抛InvalidArgumentException(不支持 CIDR) - 传
"0192.168.001.001"❌ 解析失败(不兼容带前导零的十进制)
实际使用中,建议统一用 filter_var($ip, FILTER_VALIDATE_IP) 预检,再交给 Reader;若需批量查,避免拼接字符串,改用 inet_pton() + inet_ntop() 标准化。
性能关键点:复用 Reader 实例,别每次 new
MaxMind\Db\Reader\Reader 构造函数会 mmap 整个 .mmdb 文件(默认行为),开销不小。如果在请求中反复实例化(比如 Laravel 的某个 Controller 方法里每次都 new Reader(...)),会导致大量重复 mmap / munmap,CPU 和内存抖动明显。
- 在长生命周期容器中单例化(如 Symfony 的 service、Laravel 的 singleton 绑定)
- 确认 mmap 生效:Linux 下可用
cat /proc/$(pidof php)/maps | grep mmdb查看是否驻留 - 如需禁用 mmap(例如共享主机不支持),传入选项:
['mode' => \MaxMind\Db\Reader::MODE_FILE]
真正难搞的是数据更新——.mmdb 文件被替换时,已 mmap 的进程不会自动 reload。得靠外部信号或定时器触发 Reader 重建,这点文档几乎不提,容易卡在“为什么换了库文件结果没变”。










