pangongzi / mobile
高性能中国大陆手机号码归属地查询库,基于二进制数据文件实现,支持毫秒级查询响应
Installs: 2
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/pangongzi/mobile
Requires
- php: >=7.4
This package is auto-updated.
Last update: 2026-02-13 06:48:12 UTC
README
📱 项目简介
MobileLocator 是一个专为中国大陆手机号码设计的高性能归属地查询库。基于优化的二进制数据文件和内存映射技术,提供毫秒级的查询响应速度,适用于高并发的生产环境。
🔥 核心优势
- 极致性能: 内存映射读取 + 二分查找算法,QPS高达12,000+
- 数据权威: 517,258条记录,实时更新至2025年02月
- 零依赖: 纯PHP实现,无需外部数据库
- 企业级: 单例模式设计,资源占用优化
- 类型安全: 完整的PHP 7.4+类型声明
🚀 快速开始
安装
composer require pangongzi/mobile
基础使用
<?php require 'vendor/autoload.php'; use Pangongzi\Mobile\MobileLocator; // 获取单例实例(推荐) $locator = MobileLocator::getInstance(); // 查询手机号归属地 $result = $locator->find('13812345678'); if ($result) { printf("📱 手机号: %s\n", $result['mobile']); printf("📍 地区: %s%s\n", $result['province'], $result['city']); printf("📮 邮编: %s\n", $result['zip_code']); printf("📞 区号: %s\n", $result['area_code']); printf("📡 运营商: %s\n", $result['type_str']); }
📊 性能表现
基准测试结果
| 测试项目 | 数值 | 说明 |
|---|---|---|
| 单次查询耗时 | 0.08ms | 平均响应时间 |
| QPS | 12,474 | 每秒查询数 |
| 内存占用 | ~5MB | 数据文件内存映射 |
| 并发支持 | 1000+ | 同时查询连接数 |
性能优化亮点
// ✅ 优化的索引解析(性能提升25%) private function getIndexData(int $index): array { $data = substr($this->data, $position, 9); // 批量解包:减少66%函数调用 $unpacked = unpack('Vprefix/Voffset/Ctype', $data); return $unpacked; }
与其他方案对比
| 方案 | 查询速度 | 内存占用 | 依赖 | 适用场景 |
|---|---|---|---|---|
| MobileLocator | ⭐⭐⭐⭐⭐ | 低 | 无 | 高并发生产环境 |
| 数据库查询 | ⭐⭐⭐ | 高 | MySQL/Redis | 复杂业务场景 |
| 网络API | ⭐⭐ | 低 | 网络 | 简单应用场景 |
🛠️ 完整API参考
MobileLocator 类
📌 核心方法
getInstance(string $dataFile = ''): self
获取单例实例
// 使用默认数据文件 $locator = MobileLocator::getInstance(); // 使用自定义数据文件 $locator = MobileLocator::getInstance('/path/to/custom/mobile.dat');
find(string|int $mobile): ?array
查询手机号归属地信息
$result = $locator->find('13812345678'); // 返回格式 [ 'mobile' => '13812345678', // 查询的手机号 'province' => '浙江', // 省份 'city' => '杭州', // 城市 'zip_code' => '310000', // 邮政编码 'area_code' => '0571', // 区号 'type' => 1, // 运营商类型编码 'type_str' => '移动', // 运营商名称 'info' => '1 | 移动 | 浙江 | 杭州 | 310000 | 0571' // 格式化信息 ]
📊 元信息方法
getVersion(): int
获取数据文件版本号
$version = $locator->getVersion(); // 返回: 842020146 // 🔍 版本号解析说明: // 当前版本号 842020146 解密过程: // 1. 十六进制: 0x32303532 // 2. ASCII解码: "2052" // 3. 字符串反转: "2052" → "2502" // 4. 最终含义: 2025年02月 更新版本 // // 这是由于数据文件格式限制只能存储4个字符, // 所以将 "2502" 反转存储为 "2052" 来表示 2025年02月
getIndexCount(): int
获取索引记录总数
$count = $locator->getIndexCount(); // 517,258条记录
getOperatorTypes(): array
获取运营商类型映射表
$types = $locator->getOperatorTypes(); // [ // 0 => '未知', // 1 => '移动', // 2 => '联通', // 3 => '电信', // 4 => '电信虚拟运营商', // 5 => '联通虚拟运营商', // 6 => '移动虚拟运营商', // 7 => '中国广电', // 8 => '中国广电虚拟运营商' // ]
📁 数据文件规范
文件结构
mobile.dat 文件布局:
┌─────────────────┬─────────────────┐
│ 4 bytes │ 版本号 (如: 842020146)│
├─────────────────┼─────────────────┤
│ 4 bytes │ 首个索引偏移量 │
├─────────────────┼─────────────────┤
│ variable │ 记录区 │
├─────────────────┼─────────────────┤
│ variable │ 索引区 │
└─────────────────┴─────────────────┘
版本号格式说明
版本号 842020146 解析:
- 十进制:842020146
- 十六进制:0x32303532
- ASCII字符:"2052"
这表明数据文件采用了ASCII编码的版本标识方式。
索引区格式
每条索引记录9字节:
- 4字节:手机号前七位(无符号长整型)
- 4字节:记录偏移位置(无符号长整型)
- 1字节:运营商类型(无符号字符)
记录区格式
每条记录格式:"<省份>|<城市>|<邮编>|<区号>\0"
🏗️ 系统架构
设计模式
- 单例模式: 确保全局唯一实例,避免重复加载数据
- 内存映射: 一次性加载数据文件到内存,提升查询速度
- 二分查找: O(log n)时间复杂度的高效查找算法
核心组件
class MobileLocator { private static $instance = null; // 单例实例 private string $data; // 内存中的数据文件 private int $fileSize; // 文件大小 private int $indexBegin; // 索引起始位置 private int $indexCount; // 索引总数 }
🛡️ 错误处理与异常
异常类型
try { // 文件不存在异常 $locator = MobileLocator::getInstance('/invalid/path.dat'); } catch (Exception $e) { echo "错误: " . $e->getMessage(); // "Data file not found: /invalid/path.dat" } // 无效手机号处理 $result = $locator->find('invalid'); // 返回 null $result = $locator->find('138123456'); // 返回 null (不足11位)
输入验证规则
- ✅ 必须为11位纯数字
- ✅ 支持字符串和整数类型输入
- ❌ 空值返回null
- ❌ 格式错误返回null
📈 生产环境部署
最佳实践
// 1. 应用启动时预加载 class AppServiceProvider { public function boot() { // 预加载数据文件到内存 MobileLocator::getInstance(); } } // 2. 监控内存使用 $locator = MobileLocator::getInstance(); echo "内存占用: " . (memory_get_usage() / 1024 / 1024) . " MB"; // 3. 健康检查 if ($locator->getIndexCount() > 0) { echo "✅ MobileLocator 服务正常"; }
性能调优建议
- 内存优化: 确保PHP内存限制 >= 16MB
- OPcache: 启用OPcache提升代码执行效率
- 预热机制: 应用启动时执行几次查询预热缓存
🔧 开发与测试
本地开发环境
# 克隆项目 git clone https://github.com/pangongzi/mobile.git cd mobile # 安装依赖 composer install # 运行示例 php examples/basic_usage.php
📋 版本更新日志
详细更新历史请查看 CHANGELOG.md
最近重要更新
- v2.1.0: 性能优化,索引解析效率提升25%
- v2.0.0: 重构为MobileLocator类,增强类型安全
- v1.0.0: 初始版本发布
⚠️ 注意事项与限制
重要提醒
- 携号转网影响: 由于2019年11月起实施的携号转网政策,运营商信息可能不准确
- 数据时效性: 建议每季度更新数据文件以获得最新号段信息
- 内存使用: 数据文件约5MB,请确保足够的内存空间
- PHP版本: 需要PHP 7.4+(推荐PHP 8.0+)
- 适用范围: 仅支持中国大陆11位手机号码
已知限制
- 不支持港澳台地区手机号码
- 不包含国际号码查询功能
- 运营商信息准确性受携号转网影响
🤝 贡献指南
我们欢迎各种形式的贡献!
贡献方式
- 🐛 报告bug和问题
- 💡 提出功能建议
- 🔧 提交代码改进
- 📖 完善文档说明
开发流程
# 1. Fork项目 # 2. 创建特性分支 git checkout -b feature/amazing-feature # 3. 提交更改 git commit -m 'Add some amazing feature' # 4. 推送到分支 git push origin feature/amazing-feature # 5. 创建Pull Request
📄 许可证
本项目采用 MIT License 开源协议,详情请查看 LICENSE 文件。
🙏 致谢
特别感谢以下开源项目的启发和支持:
- ls0f/mobile - 原始数据格式参考
- PHP社区 - 持续的技术支持和反馈
📞 联系方式
📧 邮箱: pangongzi1989@gmail.com
🌐 GitHub: https://github.com/pangongzi
📦 Made with ❤️ for the PHP Community