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

如何在Laravel Blade模板中展示表示文件夹结构的数组?

解决PHP多维数组转嵌套文件夹HTML列表的重复渲染问题

问题背景

你有一个表示文件结构的扁平PHP数组:

$files = [
    ["size" => "9.8 MiB", "name" => "Game.exe"],
    ["size" => "3.9 MiB", "name" => "Launcher.exe"],
    ["size" => "2 MiB", "name" => "USRDIR/mask.mpk"],
    ["size" => "1 MiB", "name" => "USRDIR/subs.hrt"],
    ["size" => "10 MiB", "name" => "USRDIR/fullhd/footage.mkv"],
];

需要生成嵌套的HTML无序列表展示文件夹结构,但当前实现会重复渲染同一文件夹(比如USRDIR会因为多个文件在其中而多次输出)。

解决方案:先转树形结构,再递归渲染

正确的做法是先在控制器中将扁平数组转换为嵌套树形结构,再在Blade模板中递归渲染,这样就能避免重复文件夹的问题。

第一步:控制器中构建树形结构

将扁平的文件数组转换为嵌套的树形结构,每个文件夹只保留一个节点,文件放在对应层级下:

// 原始$files数组处理
$fileTree = [];

foreach ($files as $file) {
    $pathParts = explode('/', $file['name']);
    $currentNode = &$fileTree;
    
    foreach ($pathParts as $index => $part) {
        $isFile = ($index === count($pathParts) - 1);
        
        if ($isFile) {
            // 添加文件节点
            $currentNode[] = [
                'type' => 'file',
                'name' => $part,
                'size' => formatBits($file['size']) // 假设formatBits是你已有的格式化函数
            ];
        } else {
            // 检查当前层级是否已存在该文件夹
            $folderFound = false;
            foreach ($currentNode as &$node) {
                if ($node['type'] === 'folder' && $node['name'] === $part) {
                    $currentNode = &$node['children'];
                    $folderFound = true;
                    break;
                }
            }
            
            // 不存在则创建新文件夹节点
            if (!$folderFound) {
                $newFolder = [
                    'type' => 'folder',
                    'name' => $part,
                    'children' => []
                ];
                $currentNode[] = $newFolder;
                $currentNode = &$newFolder['children'];
            }
        }
    }
    unset($currentNode); // 释放引用,防止后续遍历出错
}

return view('single', ['fileTree' => $fileTree]);

第二步:Blade模板递归渲染树形结构

创建一个局部视图resources/views/partials/file-tree.blade.php,用于递归渲染节点:

<ul @if($isRoot) class="root-folder" @else class="folder" @endif>
    @foreach($nodes as $node)
        @if($node['type'] === 'folder')
            <li>
                <span class="file-icon">🗀</span>{{ $node['name'] }}
                <!-- 递归渲染子节点 -->
                @include('partials.file-tree', ['nodes' => $node['children'], 'isRoot' => false])
            </li>
        @else
            <li class="file">
                <span class="file-icon">🗋</span>{{ $node['name'] }}
                <span class="file-size">({{ $node['size'] }})</span>
            </li>
        @endif
    @endforeach
</ul>

然后在主视图single.blade.php中引入这个局部视图:

@include('partials.file-tree', ['nodes' => $fileTree, 'isRoot' => true])

为什么之前的实现会重复渲染?

原来的代码是将每个文件的路径拆分后逐个输出,同一个文件夹会因为包含多个文件而被多次遍历输出。而转换为树形结构后,每个文件夹在结构中仅存在一次,递归渲染时自然只会生成一次对应的节点,彻底解决重复问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 05:28:09