
本文介绍如何从数据库查询返回的对象数组中,按“country”分组并构建多级嵌套结构(国家 → 省份 → 城市),保留原始数据关联性,避免简单去重导致关系丢失。
在实际 Web 开发中(尤其是 PHP 后端处理地理、区域类数据时),我们常遇到类似需求:数据库返回扁平化的记录列表(如 country, province, city, living_cost),但前端或业务逻辑需要按国家→省份→城市三级结构组织数据,且必须保持原始对象的完整性和字段关联性(例如后续需展示每个城市的 living_cost)。
直接使用 array_unique(array_column($data, 'country')) 只能获取国家列表,无法自然延伸出层级关系。正确做法是以国家为第一级键,省份为第二级键,城市为第三级键,构建关联数组,同时将原始对象作为叶子节点值存储——这样既实现逻辑分组,又不丢失任何原始字段。
以下是推荐的实现方式(兼容 PHP 5.5+,无需额外依赖):
$result = [];
foreach ($db_data as $item) {
$country = $item->country;
$province = $item->province;
$city = $item->city;
// 自动创建多级嵌套结构(PHP 会自动初始化缺失的数组层级)
$result[$country][$province][$city] = $item;
}
// 输出结构化结果(可用于 JSON 返回或模板渲染)
print_r($result);该方案优势显著:
- ✅ 保持数据完整性:每个 $item 对象原样保留,living_cost 等字段可随时访问(如 $result['Canada']['Ontario']['Toronto']->living_cost);
- ✅ 天然去重与聚合:相同国家+省份+城市的重复记录会自动覆盖(若需保留重复项,可改为 $result[$country][$province][$city][] = $item);
- ✅ 零依赖、高性能:纯原生 PHP 实现,时间复杂度 O(n),无函数调用开销;
- ✅ 灵活扩展:如需添加“按 living_cost 分组”,只需增加一级键:$result[$country][$province][$item->living_cost][$city] = $item;
⚠️ 注意事项:
- 确保 $db_data 是非空数组,建议前置校验:if (empty($db_data)) { return []; }
- 若字段名含空格或特殊字符,需先清洗(本例中 country/province/city 均为合法标识符);
- 如需排序输出(如国家按字母序、省份按字典序),可在构建后对 $result 执行 ksort() 或 uksort();
- 若最终需转为 JSON 供前端使用,注意 stdClass 对象可被 json_encode() 正确序列化。
通过这种键路径驱动的分组策略,你不仅能精准满足“按 country 获取 province 和 city 列表”的需求,还为后续的数据筛选、统计(如每省平均生活成本)、或生成树形菜单等场景打下坚实基础。










