
本文介绍如何从数据库查询返回的对象数组中,按指定字段(如 country)分组并构建多级嵌套结构,实现“国家 → 省份 → 城市”的层级化去重与关联组织。
在实际 Web 开发中,常需将扁平的数据库结果(如 country, province, city)转换为具有逻辑层级关系的数据结构,便于模板渲染或 API 响应。关键不在于简单去重(如 array_unique),而是在保留原始关联的前提下,按主键字段(如 'country')聚合子维度('province' 和 'city')。
最直接、高效且可读性强的方式是使用 嵌套关联数组 进行一次遍历构建:
$result = [];
foreach ($db_data as $item) {
$country = $item->country;
$province = $item->province;
$city = $item->city;
// 自动创建多级键:$result['Canada']['Ontario']['Toronto'] = $item
$result[$country][$province][$city] = $item;
}该方案天然支持重复值覆盖(若同一城市出现多次,后者覆盖前者),且完全保留原始对象的所有属性(如 living_cost),后续可随时扩展访问。例如:
// 获取加拿大安大略省的所有城市名
$citiesInOntario = array_keys($result['Canada']['Ontario'] ?? []);
// 遍历所有国家及其省份
foreach ($result as $country => $provinces) {
echo "- {$country}\n";
foreach ($provinces as $province => $cities) {
echo " - {$province}\n";
foreach (array_keys($cities) as $city) {
echo " - {$city}\n";
}
}
}✅ 优势说明:
- 零依赖:仅用原生 PHP 数组语法,无需额外函数或扩展;
- 高性能:O(n) 时间复杂度,单次遍历完成全部分组;
- 强关联性:每个城市仍绑定其原始对象,可安全访问 living_cost 等任意字段;
- 自动去重:同名城市在同一省份下仅保留一份(键名唯一),符合“逻辑唯一”需求。
⚠️ 注意事项:
- 若需严格保留重复城市(如不同时间戳记录),请改用 [] 追加($result[$country][$province][] = $item;);
- 字段名需确保存在且非 null,建议在循环内添加 isset() 或 !empty() 校验以增强健壮性;
- 输出前可用 ksort() 对国家/省份键排序,提升可读性(如 ksort($result); foreach ($result as $country => $provinces) { ksort($provinces); ... })。
此方法兼顾简洁性与工程实用性,是处理层级化地理数据、分类标签、多维统计等场景的经典实践。










