pangongzi/mobile

高性能中国大陆手机号码归属地查询库,基于二进制数据文件实现,支持毫秒级查询响应

Installs: 2

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/pangongzi/mobile

v0.0.2 2026-02-13 06:44 UTC

This package is auto-updated.

Last update: 2026-02-13 06:48:12 UTC


README

Latest Stable Version Total Downloads License PHP Version Build Status

📱 项目简介

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 服务正常";
}

性能调优建议

  1. 内存优化: 确保PHP内存限制 >= 16MB
  2. OPcache: 启用OPcache提升代码执行效率
  3. 预热机制: 应用启动时执行几次查询预热缓存

🔧 开发与测试

本地开发环境

# 克隆项目
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: 初始版本发布

⚠️ 注意事项与限制

重要提醒

  1. 携号转网影响: 由于2019年11月起实施的携号转网政策,运营商信息可能不准确
  2. 数据时效性: 建议每季度更新数据文件以获得最新号段信息
  3. 内存使用: 数据文件约5MB,请确保足够的内存空间
  4. PHP版本: 需要PHP 7.4+(推荐PHP 8.0+)
  5. 适用范围: 仅支持中国大陆11位手机号码

已知限制

  • 不支持港澳台地区手机号码
  • 不包含国际号码查询功能
  • 运营商信息准确性受携号转网影响

🤝 贡献指南

我们欢迎各种形式的贡献!

贡献方式

  1. 🐛 报告bug和问题
  2. 💡 提出功能建议
  3. 🔧 提交代码改进
  4. 📖 完善文档说明

开发流程

# 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