You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Laravel的allDirectories()输出转换为层级目录树多维数组

问题描述

首先我已经查阅了所有能找到的相关资源示例,但是没找到足够贴合的方案来解决这个问题,尽管问题看起来并不复杂。我还看到有一个相同的同类问题至今没有得到解决,我的场景和该问题完全一致,因此直接使用相同的示例数据。

我调用Laravel的allDirectories()函数得到的输出大致如下:

array:20 [▼
  0 => "test"
  1 => "files"
  2 => "files/2"
  3 => "files/2/Blocks"
  4 => "files/2/Blocks/thumbs"
  5 => "files/shares"
]

我希望将其转换为如下格式的多维数组:

[
    ["label" => "test", "path" => "test", "children" => []],
    ["label" => "files", "path" => "files", "children" =>
        [
            ["label" => "2", "path" => "files/2", "children" =>
                [
                    ["label" => "Blocks", "path" => "files/2/Blocks", "children" =>
                        [
                            [
                                "label" => "thumbs",
                                "path" => "files/2/Blocks/thumbs",
                                "children" => []
                            ]
                        ]
                    ]
                ]
            ],
            ["label" => "shares", "path" => "files/shares", "children" => []]
        ]
    ],
];

请问要如何操作才能将allDirectories()的输出转换为上述结构的多维数组?


解决方案

你可以通过路径分层遍历+引用映射的方式实现转换,核心逻辑是先处理短路径(父目录)再处理长路径(子目录),用映射表快速定位父节点位置,避免递归遍历查找损耗。

完整实现代码如下:

// 第一步:获取allDirectories返回的路径数组,替换为你自己的路径获取逻辑
$directories = Storage::allDirectories();

// 第二步:按路径长度排序,保证父目录一定比子目录先处理
usort($directories, function($a, $b) {
    return strlen($a) - strlen($b);
});

$tree = [];
// 路径映射表,存储每个路径对应的节点引用,方便快速查找
$pathMap = [];

foreach ($directories as $path) {
    // 拆分路径段
    $segments = explode('/', $path);
    // 当前节点的标签是最后一个路径段
    $label = end($segments);
    $currentNode = [
        'label' => $label,
        'path' => $path,
        'children' => []
    ];
    
    // 根目录(没有父路径)直接加到根树
    if (count($segments) === 1) {
        $tree[] = $currentNode;
        // 把当前节点的引用存到映射表
        $pathMap[$path] = &$tree[count($tree) - 1];
    } else {
        // 取出父路径:去掉最后一个路径段再拼接
        array_pop($segments);
        $parentPath = implode('/', $segments);
        // 父节点肯定已经在映射表中(因为提前做了排序)
        $parentNode = &$pathMap[$parentPath];
        // 把当前节点加到父节点的children数组
        $parentNode['children'][] = $currentNode;
        // 把当前节点的引用存到映射表
        $pathMap[$path] = &$parentNode['children'][count($parentNode['children']) - 1];
    }
    
    // 解除引用,避免后续循环变量覆盖导致异常
    unset($currentNode);
}

// 最终$tree就是你需要的结构
dd($tree);

逻辑说明

  • 路径排序是核心前提,保证父目录处理时子目录还未处理,父节点已经存在于映射表中
  • 引用映射表避免了每次查找父节点都要遍历整棵树,处理大量目录时效率更高
  • 代码兼容任意层级的目录嵌套,不需要提前知道目录深度

内容的提问来源于stack exchange,提问作者Marcel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 21:54:04