youvision / think-regions
ThinkPHP 8 省市区(县)街道四级联动扩展,支持中文、拼音、首字母搜索,内置数据安装命令。
Requires
- php: >=8.0
- topthink/framework: ^8.0
Requires (Dev)
- phpunit/phpunit: ^9.6 || ^10.5 || ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
面向 ThinkPHP 的开源工程索引:组件、框架、服务与发布工具,按能力组织,持续整理。 仓库地址:https://github.com/indiboy-create/ThinkPHP-PanGu/ 在线站点:https://indiboy-create.github.io/ThinkPHP-PanGu/
youvision/think-regions
ThinkPHP 8 省市区(县)街道四级联动扩展。
使用模型查询、服务注册、自动路由与独立安装命令,支持中文名称、拼音、首字母搜索。
特性
- 四级联动:省、市、区(县)、街道,按
parent_id逐级获取 - 关键字搜索:支持中文、全拼、首字母
- 模型查询:全部查询通过 ThinkPHP Model 完成,不直接写
Db::查询 - 自动路由:服务启动时自动注册
/regions/*接口,可通过配置关闭 - 一键安装:内置
data/regions.csv,php think regions:install自动建表并导入全国数据 - 多数据源:支持远程或本地 CSV,适合内网离线部署
- 配置化:表名、连接、字段、排序、缓存、搜索字段、路由前缀均可配置
- 多数据库:建表逻辑支持 MySQL、SQLite、PostgreSQL、SQL Server
- 门面与依赖注入:支持
Regions门面、容器注入与直接实例化
环境要求
- PHP >= 8.0
- ThinkPHP 8
- 数据库:MySQL / SQLite / PostgreSQL / SQL Server
- PHP 扩展:
pdo(可选mbstring,用于自动识别 GBK 编码)
安装
composer require youvision/think-regions
服务通过 Composer 的 extra.think.services 声明。若项目配置了 service:discover,安装后会自动注册;也可手动执行:
php think service:discover
初始化数据
一键安装(推荐)
包内已内置 data/regions.csv,可直接执行安装;也可通过 csv_file、csv_url、--file 或 --url 指定其他数据源。
php think regions:install
该命令会:
- 检查数据表是否存在,不存在时自动创建;
- 表内没有数据时,优先使用
--file、--url、csv_file、csv_url,均未指定时使用包内data/regions.csv; - 表内已有数据时停止导入,避免误覆盖。
常用参数:
# 删除并重建数据表后重新导入 php think regions:install --force # 使用本地 CSV 文件 php think regions:install --file=/data/regions.csv # 临时指定远程 CSV 地址 php think regions:install --url=http://example.com/regions.csv # 调整每批写入条数 php think regions:install --chunk=1000
CSV 首行建议包含表头,支持
id、pid、deep、name、pinyin_prefix、pinyin、ext_id、ext_name;也兼容旧字段名与无表头解析。编码支持 UTF-8 与 GBK。
配置
包内默认配置会在服务注册时自动合并,无需发布即可使用。需要修改默认值时:
php think regions:publish
配置文件会发布到项目 config/regions.php。目标文件已存在时跳过,追加 --force 可覆盖。
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
table |
string |
regions |
数据表名,不含数据库前缀 |
connection |
string |
'' |
数据库连接标识,留空使用默认连接 |
field |
string |
id,name,parent_id,level |
列表查询返回字段 |
order |
string |
adcode asc,id asc |
查询排序 |
cache |
int|false |
86400 |
查询缓存秒数,false 关闭 |
cache_key |
string |
think-regions |
查询缓存键前缀 |
search_fields |
array |
['name','pinyin_prefix','pinyin','ext_name'] |
关键字搜索字段,支持 CSV 字段名 |
max_level |
int |
4 |
数据最大层级 |
level_names |
array |
省/市/区县/街道 | 层级名称映射 |
route |
bool |
true |
是否自动注册路由 |
route_prefix |
string |
regions |
自动路由前缀 |
route_middleware |
array |
[] |
自动路由中间件 |
csv_url |
string |
'' |
远程 CSV 下载地址,为空时使用包内数据 |
csv_file |
string |
'' |
本地 CSV 文件,非空时优先于 csv_url |
chunk_size |
int |
500 |
批量写入条数 |
以上配置均已在实际查询、建表、导入和路由注册流程中生效;
getPath()与getAddress()会自动使用必要字段,不受field限制。
路由
开启 route 后,服务会自动注册以下接口,默认前缀为 /regions,同时响应 GET 与 POST 请求:
| 地址 | 参数 | 说明 |
|---|---|---|
/regions/getRegion |
parent_id,默认 0 |
获取指定父级下的地区,0 返回省份 |
/regions/getProvince |
无 | 获取省份 |
/regions/getCity |
parent_id |
获取城市 |
/regions/getDistrict |
parent_id |
获取区(县) |
/regions/getStreet |
parent_id |
获取街道 |
/regions/searchRegion |
keywords、parent_id |
搜索地区 |
/regions/searchProvince |
keywords |
搜索省份 |
/regions/searchCity |
keywords、parent_id |
搜索城市 |
/regions/searchDistrict |
keywords、parent_id |
搜索区(县) |
/regions/searchStreet |
keywords、parent_id |
搜索街道 |
/regions/getById |
id |
根据主键获取单条地区 |
/regions/getByAdcode |
adcode |
根据行政区划编码获取单条地区 |
/regions/getPath |
id |
获取从省份到当前地区的路径 |
/regions/getAddress |
id、separator |
获取完整地址名称 |
返回值为 JSON 数组,例如:
[
{ "id": 1, "name": "北京市", "parent_id": 0, "level": 1 }
]
手动注册路由
关闭自动路由:
// config/regions.php 'route' => false,
然后在路由文件中自行注册:
use think\facade\Route; use Youvision\ThinkRegions\RegionController; Route::group('regions', function () { Route::rule('getRegion', RegionController::class . '@getRegion', 'GET|POST'); Route::rule('getProvince', RegionController::class . '@getProvince', 'GET|POST'); Route::rule('getCity', RegionController::class . '@getCity', 'GET|POST'); Route::rule('getDistrict', RegionController::class . '@getDistrict', 'GET|POST'); Route::rule('getStreet', RegionController::class . '@getStreet', 'GET|POST'); Route::rule('searchRegion', RegionController::class . '@searchRegion', 'GET|POST'); });
门面
use Youvision\ThinkRegions\Facade\Regions; Regions::getProvince(); Regions::getCity(1); Regions::getDistrict(2); Regions::getStreet(3); Regions::searchProvince('广东'); Regions::searchCity('sz', 1); Regions::getById(4); Regions::getByAdcode('440515'); Regions::getPath(4); Regions::getAddress(4, '/'); Regions::getLevelName(4);
依赖注入
use Youvision\ThinkRegions\Regions; class Address { public function __construct(protected Regions $regions) { } public function cities(int $provinceId): array { return $this->regions->getCity($provinceId); } }
直接实例化
use Youvision\ThinkRegions\Regions; $regions = new Regions([ 'table' => 'regions', 'cache' => false, 'order' => 'name asc', ]); $provinces = $regions->getProvince();
数据格式
导入数据为 CSV,推荐使用以下格式:
id,pid,deep,name,pinyin_prefix,pinyin,ext_id,ext_name 11,0,0,"北京","b","bei jing","110000000000","北京市" 1101,11,1,"北京","b","bei jing","110100000000","北京市" 110101,1101,2,"东城","d","dong cheng","110101000000","东城区"
字段映射:
pid→parent_iddeep→level,导入时自动加 1(0 省、1 市、2 区县、3 街道)ext_id→adcodeext_name→name,无ext_name时回退到namepinyin_prefix→initialpinyin导入时自动去除空格- 缺少
citycode、lng_lat时写入空字符串
兼容性:
- 编码支持 UTF-8、GBK/GB18030
- 表头支持英文字段名或常用中文表头,如“名称”“父级”“区域编码”
- 无表头时按
id,pid,deep,name,pinyin_prefix,pinyin,ext_id,ext_name顺序解析 - 字段包含逗号、引号或换行时,使用双引号包裹并按 CSV 规则转义
- 层级约定:
1省、2市、3区/县、4街道
多应用模式
在多应用模式下,自动路由会注册为全局路由,前缀为 /regions。如果多个应用需要独立接口,建议:
- 将
route_prefix改为api/regions、v1/regions等; - 或关闭
route,在对应应用的路由文件中单独注册; - 不同应用使用不同的
table或connection实现数据隔离。
数据库与缓存说明
- 建表支持 MySQL、SQLite、PostgreSQL、SQL Server;索引会自动创建。
- 导入数据使用事务与分批写入,SQLite、SQL Server 会根据绑定参数上限自动调小批次。
- 查询缓存默认开启 1 天。重新导入数据后可清理
cache_key前缀对应的缓存,或临时将cache设为false。
示例
examples/region.html 是基于 layui 的四级联动与关键字搜索示例,将文件放入项目 public 目录后访问,并按需修改接口前缀。
测试
composer install php -d extension=pdo_sqlite -d extension=sqlite3 vendor/bin/phpunit
测试使用 SQLite 内存数据库,覆盖逐级查询、中文/拼音/首字母搜索、路径与地址、配置项生效、本地 CSV 导入、编码与表头解析、建表与清空等场景。
许可
MIT