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

一个自定义PHP函数递归地迭代目录并输出一个分层的多维数组?,php,arrays,recursion,multidimensional-array,iterator,Php,Arrays,Recursion,Multidimensional Array,Iterator,一个自定义PHP函数递归地迭代目录并输出一个分层的多维数组 使用新的SPL迭代器类(RecursiveIterator*),我一直在处理以下函数: 这将导致以下输出: Array ( [0] => Array ( [name] => Anchor Links [file] => anchor-links.php ) [1] => Array (

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

使用新的SPL迭代器类(RecursiveIterator*),我一直在处理以下函数: 这将导致以下输出:

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
                )

        )

)
然而,我试图实现的输出如下:

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
                        )

                )

        )
)

我想我们就快到了,我只是在想如何让子目录输出到[children]中(现在)的空数组。另外,不要混淆重复或相似的名称(例如,同一目录中有一个right-sidebar.php文件和一个right-sidebar子目录)。

如果您的目标是递归扫描给定目录(包括其子目录),并以分层方式返回包含所有文件夹和文件的多维数组,下面的函数:deepScan()可以帮助您

此函数只接受一个参数:
$directory
,它是要扫描的目录的路径。其他2个参数只是用于在递归过程中跟踪事物,因此应该单独使用

该函数返回一个多维数组,其中目录和子目录的名称作为键。每个子目录中的所有文件都列为该子目录的子目录

<?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>";
使用,以及一些参考杂耍,您可以通过一个显式循环来实现这一点

请注意这个标志
recursivedirectoryinterator::SKIP_DOTS
它过滤掉
文件

有一点很重要。使用应该可以避免使用显式嵌套循环。当您发现自己在这里使用显式嵌套循环时,您可能没有正确使用迭代器,或者迭代器本身不适合该任务(可能这是递归函数的域)。当然,总是存在边缘情况,但对于大多数情况,这条规则适用

<?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>";
function directoryToArray($directory)
{
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator(
            $directory,
            RecursiveDirectoryIterator::SKIP_DOTS
        ),
        RecursiveIteratorIterator::SELF_FIRST
    );

    $files = [];
    $references = [&$files];
    foreach ($iterator as $item) {
        $file = [
            'name' => $item->getFilename(),
            'file' => $item->getFilename(),
        ];

        if ($item->isDir()) {
            $file['children'] = [];

            $references[$iterator->getDepth() + 1] =& $file['children'];
        }

        $references[$iterator->getDepth()][] = $file;
    }

    unset($references);

    return $files;
}