doujiong2533 2016-09-08 11:20
浏览 52

一个自定义PHP函数,用于递归迭代目录并输出分层的多维数组?

A custom PHP function to recursively iterate over directories and output a hierarchical, multidimensional array?

Using the new SPL Iterator class (RecursiveIterator*), I've been working on the following function:

function directoryToArray( $directory ) {

    $array = [];

    $objects = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $directory ), RecursiveIteratorIterator::SELF_FIRST );

    foreach ( $objects as $name => $object ) {

        if ( !( $object->getFilename() == "." | $object->getFilename() == ".." ) ) {
            $path = $object->isDir() ? [
                    [
                        'name' => $object->getFilename(),
                        'file' => $object->getFilename(),
                        'children' => []
                    ]
            ] : [
                [
                    'name' => friendlyName( $object->getFilename() ),
                    'file' => $object->getFilename(),
                ]
            ];

            for ( $depth = $objects->getDepth() - 1; $depth >= 0; $depth-- ) {
                $path = [
                    $objects->getSubIterator( $depth )->current()->getFilename() => $path,
                ];
            }

            $array = array_merge_recursive( $array, $path );

        }

    }
    return $array;
}

This currently results in the following output:

Array
(
    [0] => Array
        (
            [name] => Anchor Links
            [file] => anchor-links.php
        )

    [1] => Array
        (
            [name] => Columns
            [file] => columns.php
        )

    [2] => Array
        (
            [name] => Page Layouts
            [file] => page-layouts
            [children] => Array
                (
                )

        )

    [page-layouts] => Array
        (
            [0] => Array
                (
                    [name] => Right Sidebar
                    [file] => right-sidebar.php
                )

            [1] => Array
                (
                    [name] => Left Sidebar
                    [file] => left-sidebar.php
                )

            [2] => Array
                (
                    [name] => Right Sidebar
                    [file] => right-sidebar
                    [children] => Array
                        (
                        )

                )

            [right-sidebar] => Array
                (
                    [0] => Array
                        (
                            [name] => Other Options
                            [file] => other-options.php
                        )

                    [1] => Array
                        (
                            [name] => Option A
                            [file] => option-a.php
                        )

                    [2] => Array
                        (
                            [name] => Other Options
                            [file] => other-options
                            [children] => Array
                                (
                                )

                        )

                    [other-options] => Array
                        (
                            [0] => Array
                                (
                                    [name] => Sample
                                    [file] => sample.php
                                )

                        )

                )

            [3] => Array
                (
                    [name] => Changelog
                    [file] => changelog.php
                )

        )

)

However, the output I'm trying to achieve is the following:

Array
(
    [0] => Array
        (
            [name] => Anchor Links
            [file] => anchor-links.php
        )

    [1] => Array
        (
            [name] => Columns
            [file] => columns.php
        )

    [2] => Array
        (
            [name] => Page Layouts
            [file] => page-layouts
            [children] => Array
                (

                    [0] => Array
                        (
                            [name] => Right Sidebar
                            [file] => right-sidebar.php
                        )

                    [1] => Array
                        (
                            [name] => Left Sidebar
                            [file] => left-sidebar.php
                        )

                    [2] => Array
                        (
                            [name] => Right Sidebar
                            [file] => right-sidebar
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [name] => Other Options
                                            [file] => other-options.php
                                        )

                                    [1] => Array
                                        (
                                            [name] => Option A
                                            [file] => option-a.php
                                        )

                                    [2] => Array
                                        (
                                            [name] => Other Options
                                            [file] => other-options
                                            [children] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [name] => Sample
                                                            [file] => sample.php
                                                        )
                                                )

                                        )

                                )

                        )

                    [3] => Array
                        (
                            [name] => Changelog
                            [file] => changelog.php
                        )

                )

        )
)

I think we're almost there, I'm just stumped on how to get the subdirectories to output to the (now) empty array inside of [children]. Also, do not be confused about the duplicate or similar names (e.g., there is a right-sidebar.php file and a right-sidebar subdirectory in the same directory).

  • 写回答

2条回答 默认 最新

  • douban5644 2016-09-08 15:38
    关注

    If your goal is to recursively scan a given directory (including its sub-directories) and return a Multidimensional Array with all the Folders & Files in a hierarchical fashion, the Function below: deepScan() could help you out.

    This Function takes only one Parameter: $directory which is the Path to the Directory to scan. The other 2 Arguments are just for keeping track of things during the Recursions and thus should be left alone.

    The Function returns a Multidimensional Array with the names of Directories & Sub-Directories as the Keys. All Files in each Sub-Directory are listed as children of that Sub-Directory.

    <?php
    
    
        /**
         * THIS FUNCTION SCANS A DIRECTORY "RECURSIVELY",
         * BUILDING AN ARRAY TREE OF ALL FILES AND FOLDERS AS IT GOES...
         * THIS IMPLIES THAT EVEN SUB-DIRECTORIES WILL BE SCANNED AS WELL
         *
         * FULL-PATH TO THE DIRECTORY TO SCAN
         * @param $directory
         *
         * USED INTERNALLY DURING THE RECURSIVE TRIPS. LEAVE AS IS
         * @param $k
         *
         * USED INTERNALLY DURING THE RECURSIVE TRIPS. LEAVE AS IS
         * @param $key
         *
         * RETURNS THE RESULTING ARRAY
         * @return array
         */
        function deepScan($directory, &$k=null, $key=null) {
            $iterator           = new \DirectoryIterator ($directory);
            $firstDir           = basename($directory);
            $dirs               = [];
            $dirs[$firstDir]    = [];
    
            if(!$key){  $key    = $firstDir;    }
            if(!$k){    $k      = &$dirs[$key]; }
            if($k && $key){
                $k[$key]        = [];
                $k              = &$k[$key];
            }
    
            foreach($iterator as $info) {
                $fileDirName            = $info->getFilename();
                if($info->isFile () && !preg_match("#^\..*?#", $fileDirName)){
                    $k[]                = $directory . DIRECTORY_SEPARATOR . $fileDirName;
                }else if($info->isDir()  && !$info->isDot()){
                    $pathName           = $directory . DIRECTORY_SEPARATOR . $fileDirName;
                    $k[$fileDirName]    = $pathName;
                    $key                = $fileDirName;
                    $it                 = &$k;
                    deepScan($pathName, $it, $key);
                }
            }
    
            $dirs   = removeEmptyEntries($dirs);
    
            return $dirs;
        }
    
        /**
         * THIS FUNCTION REMOVES/FILTERS EMPTY ENTRIES
         * FROM THE RESULTING ARRAY TREE.
         *
         * THE ARRAY TO BE FILTERED
         * @param $data
         *
         * RETURNS THE RESULTING FILTERED ARRAY
         * @return array
         */
        function removeEmptyEntries(array &$data){
            foreach($data as $key=>&$item){
                if(is_array($item)){
                    if(empty($item)) {
                        unset($data[$key]);
                    }else{
                        removeEmptyEntries($item);
                    }
                }
            }
            foreach($data as $key=>&$item){
                if(is_array($item) && empty($item)) {
                    unset($data[$key]);
                }
            }
            return $data;
        }
    
    
        // USAGE:
        $dirTree  = deepScan( "/path_2_specific_directory" );
    
        echo "<pre>";
        print_r($dirTree);
        echo "</pre>";
    

    It is hoped this gives you what you need. You might, however, tweak it further if you want so special output.

    Cheers and Good Luck ;-)

    评论

报告相同问题?

悬赏问题

  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么