
本文介绍一种利用 laravel 的 arr::dot 和集合工具高效提取嵌套数组所有层级路径(不含叶节点值)的方法,支持任意深度结构,并自动去重、标准化输出格式。
本文介绍一种利用 laravel 的 arr::dot 和集合工具高效提取嵌套数组所有层级路径(不含叶节点值)的方法,支持任意深度结构,并自动去重、标准化输出格式。
在处理复杂嵌套配置、权限结构或 API Schema 映射时,常需将多维数组“扁平化”为可读性强的点号路径(如 company.contacts.phones),用于日志记录、权限校验、表单绑定或动态渲染。关键要求是:仅保留键路径,排除纯数值叶节点(如 'test'、'postal_code'),且路径需覆盖所有中间层级(如同时包含 company.contacts 和 company.contacts.phones)。
Laravel 内置的 Arr::dot() 方法正是解决此问题的理想工具——它递归遍历数组,将嵌套键转为点号分隔字符串,并忽略纯标量值(即只对子数组生成路径)。配合集合链式操作,可简洁实现目标:
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
$array = [
'company' => [
'contacts' => [
'first_names',
'last_name',
'emails',
'phones' => ['test'],
],
'addresses' => ['postal_code'],
],
];
$paths = collect(Arr::dot($array))
->keys() // 获取所有点号路径(如 'company.contacts.phones.0')
->map(fn($key) => Str::beforeLast($key, '.')) // 截断末尾索引(如移除 '.0')
->unique() // 去重(避免同一路径因多个叶节点重复出现)
->values() // 重置键为连续数字索引
->all(); // 转为普通数组
print_r($paths);
// 输出:
// Array
// (
// [0] => company.contacts
// [1] => company.contacts.phones
// [2] => company.addresses
// )
✅ 核心原理说明:
- Arr::dot($array) 将嵌套结构转为扁平关联数组,键为完整路径(如 ['company.contacts.phones.0' => 'test']),仅对数组类型子项生成路径,跳过纯字符串/数字叶节点;
- keys() 提取所有路径字符串;
- Str::beforeLast($key, '.') 安全移除末尾索引(如 .0、.1),确保路径指向容器而非具体元素;
- unique() 消除因同层多个叶节点导致的路径重复(例如 contacts 下有 3 个字符串,会生成 3 条相同前缀路径)。
⚠️ 注意事项:
- 此方案依赖 Laravel 支持。若在非 Laravel 环境中使用,需手动实现 Arr::dot 逻辑(可参考其源码,或使用 array_walk_recursive 自定义递归提取);
- 若需严格匹配示例输出(仅两级路径),可在 map 后添加 filter(fn($path) => substr_count($path, '.') >= 1) 限定最小深度;
- 路径顺序取决于数组遍历顺序,如需字典序排序,追加 ->sort()->values() 即可。
该方法兼具简洁性与健壮性,一行核心逻辑即可应对任意嵌套深度,是处理配置路径映射的推荐实践。










