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

PHP中如何遍历动态深度数组?优化目录路径生成代码

问题描述

需要实现文件引入时获取指定目录的绝对路径,目前已有一个基于已知文件结构遍历数组的函数,但代码嵌套多层十分冗余。尝试过DirectoryIterator及IteratorIterator,但无法实现所需的控制逻辑。部分目录(如图像目录)存在动态子文件夹,无需硬编码,想知道是否有更简洁的PHP内置函数实现方式,替代当前的冗余代码。

原代码如下:

protected function getRoot() {
    $directories = [
        'css' => '',
        'demo' =>['clientImages',['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]],
        'includes' => ['class','inc','js'],
        'login' => ['logImages',['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]],
        'public' => [['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]],
        'recover' => [['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]],
        'registration' => [['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]],
        'siteImages' => '',
        'tracker' => ['clientImages',['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]]
    ];
    
    foreach($directories as $path => $dirs){
        $this->root[$path] = $this->getSiteRoot().$path.'/';
        
        if(is_array($dirs)){
            foreach($dirs as $dir => $sub){
                if(is_array($sub)){
                    foreach($sub as $s => $d){
                            
                        $this->root[$path.'-'.$s] = $this->root[$path].$s.'/';
                        if(is_array($d)){
                            foreach($d as $b => $a){
                
                                $this->root[$path.'-'.$b] = $this->root[$path.'-'.$s].$b.'/';
                                if(is_array($a)){
                                    foreach($a as $z){
                                        
                                        $this->root[$path.'-'.$z] = $this->root[$path.'-'.$b].$z.'/';
                                    }
                                }
                            }
                        } else {
                            
                            $this->root[$path.'-'.$s] = $this->root[$path.'-'.$s].$d.'/';
                        }
                    }
                } else {
                    $this->root[$path.'-'.$sub] = $this->root[$path].$sub.'/';
                }
            }
        }
    }
return $this->root;
}
解决方案

1. 用递归函数替代多层嵌套循环

原代码的核心问题是用多层foreach处理嵌套数组,递归函数可以大幅简化逻辑,同时保留对目录结构的精确控制:

protected function getRoot() {
    $directories = [
        'css' => '',
        'demo' =>['clientImages',['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]],
        'includes' => ['class','inc','js'],
        'login' => ['logImages',['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]],
        'public' => [['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]],
        'recover' => [['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]],
        'registration' => [['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]],
        'siteImages' => '',
        'tracker' => ['clientImages',['config' => ['includes' => ['class','js']]],['src' => ['libs' => '']]]
    ];

    $this->root = [];
    $siteRoot = $this->getSiteRoot();

    // 递归处理目录结构的闭包函数
    $processDirs = function($currentPath, $dirStructure, $parentKey) use (&$processDirs, $siteRoot, &$root) {
        foreach ($dirStructure as $key => $value) {
            if (is_numeric($key)) {
                // 处理索引数组项(如['clientImages'])
                $dirName = $value;
                $newKey = $parentKey . '-' . $dirName;
                $newPath = $currentPath . $dirName . '/';
                $root[$newKey] = $newPath;
                
                // 自动获取动态目录的子文件夹
                if (in_array($dirName, ['clientImages', 'logImages', 'siteImages'])) {
                    $dynamicSubdirs = glob($newPath . '*', GLOB_ONLYDIR);
                    foreach ($dynamicSubdirs as $subdir) {
                        $subdirName = basename($subdir);
                        $root[$newKey . '-' . $subdirName] = $subdir . '/';
                    }
                }
            } else {
                // 处理关联数组项(如['config' => [...]])
                $newKey = $parentKey . '-' . $key;
                $newPath = $currentPath . $key . '/';
                $root[$newKey] = $newPath;
                
                // 存在子结构则递归处理
                if (is_array($value)) {
                    $processDirs($newPath, $value, $newKey);
                }
            }
        }
    };

    // 遍历顶层目录
    foreach ($directories as $topDir => $subStructure) {
        $topPath = $siteRoot . $topDir . '/';
        $this->root[$topDir] = $topPath;
        if (!empty($subStructure)) {
            $processDirs($topPath, $subStructure, $topDir);
        }
    }

    return $this->root;
}

2. 动态目录处理

对于clientImages这类存在动态子文件夹的目录,用glob($path . '*', GLOB_ONLYDIR)可以自动获取所有子目录,无需硬编码。如果需要更复杂的目录遍历规则,也可以结合RecursiveDirectoryIterator和RecursiveIteratorIterator,但glob()在这个场景下更轻量直接。

3. 关于DirectoryIterator的使用说明

DirectoryIterator适合遍历真实存在的物理目录,但你的场景需要结合预设的目录结构规则(部分目录是硬编码的逻辑)和动态目录,递归处理预设数组+glob()动态获取的组合,比单纯用目录迭代器更贴合需求,能保留对目录键名的自定义控制(比如demo-config这类命名规则)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:53:19