将PHP递归文件夹扫描转换为多维数组(包括子文件夹和文件)

5

目前我有些迷茫。我的目标是递归扫描一个带子文件夹的文件夹,每个子文件夹中都有图片,将其放入多维数组中,然后能够解析每个子文件夹及其包含的图片。

我有以下起始代码,基本上是扫描每个包含文件的子文件夹,现在只是无法将其放入多维数组中。

$dir = 'data/uploads/farbmuster';
$results = array();

if(is_dir($dir)) {
    $iterator = new RecursiveDirectoryIterator($dir);

    foreach(new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST) as $file) {
        if($file->isFile()) {
            $thispath = str_replace('\\','/',$file->getPath());
            $thisfile = utf8_encode($file->getFilename());

            $results[] = 'path: ' . $thispath. ',  filename: ' . $thisfile;
        }
    }
}

有人能帮我解决这个问题吗?

提前感谢您的帮助!


你需要存储文件的数组必须是多维的,这样做有特定的原因吗?如果没有,那么这只会让问题变得更加困难,而不是解决它。 - MarcDefiant
是的,有一个具体的原因:这是一个我正在使用的简单CMS,用户可以动态地上传图像到预定义的文件夹/子文件夹中。这个CMS有点棘手,所以我需要调用这个函数来获取所有按子文件夹分类的图像并显示它。例如:子文件夹1将被显示为标题,其包含的所有图像在此之后显示,然后下一个文件夹2作为标题和其包含的图像等等。

1

Image1 Image2

2

Image1 Image2
- Ben G
可能是重复问题:https://dev59.com/jE_Ta4cB1Zd3GeqPFv8q - MarcDefiant
3个回答

10

你可以尝试

$dir = 'test/';
$results = array();
if (is_dir($dir)) {
    $iterator = new RecursiveDirectoryIterator($dir);
    foreach ( new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST) as $file ) {
        if ($file->isFile()) {
            $thispath = str_replace('\\', '/', $file);
            $thisfile = utf8_encode($file->getFilename());
            $results = array_merge_recursive($results, pathToArray($thispath));
        }
    }
}
echo "<pre>";
print_r($results);

输出

Array
(
    [test] => Array
        (
            [css] => Array
                (
                    [0] => a.css
                    [1] => b.css
                    [2] => c.css
                    [3] => css.php
                    [4] => css.run.php
                )

            [CSV] => Array
                (
                    [0] => abc.csv
                )

            [image] => Array
                (
                    [0] => a.jpg
                    [1] => ab.jpg
                    [2] => a_rgb_0.jpg
                    [3] => a_rgb_1.jpg
                    [4] => a_rgb_2.jpg
                    [5] => f.jpg
                )

            [img] => Array
                (
                    [users] => Array
                        (
                            [0] => a.jpg
                            [1] => a_rgb_0.jpg
                        )

                )

        )

使用的函数

function pathToArray($path , $separator = '/') {
    if (($pos = strpos($path, $separator)) === false) {
        return array($path);
    }
    return array(substr($path, 0, $pos) => pathToArray(substr($path, $pos + 1)));
}

无法正常工作。 upload/ 包含一些子文件夹中的图像文件,例如: "users/image/2014/jun" "users/images/2014/may"返回的数组包含: upload > users > images > 2014 > may .... upload > users > images > 2015 > may .... upload > users > images > 2016 > jun ....其中2015和2016不是目录,也不存在。 - Braza

2

RecursiveDirectoryIterator 会递归地扫描一个平面结构。要创建一个深层次的结构,您需要使用 DirectoryIterator 创建一个递归函数(调用自身)。如果当前文件 isDir() 并且 !isDot(),则通过使用新目录作为参数再次调用该函数进行深入操作。然后将新数组附加到当前集合中。

如果您无法处理此内容,请告诉我,我将在此处放置一些代码。必须对其进行文档(现在有忍者注释),因此……尝试我的懒惰方法,使用说明。

代码

/**
 * List files and folders inside a directory into a deep array.
 *
 * @param string $Path
 * @return array/null
 */
function EnumFiles($Path){
    // Validate argument
    if(!is_string($Path) or !strlen($Path = trim($Path))){
        trigger_error('$Path must be a non-empty trimmed string.', E_USER_WARNING);
        return null;
    }
    // If we get a file as argument, resolve its folder
    if(!is_dir($Path) and is_file($Path)){
        $Path = dirname($Path);
    }
    // Validate folder-ness
    if(!is_dir($Path) or !($Path = realpath($Path))){
        trigger_error('$Path must be an existing directory.', E_USER_WARNING);
        return null;
    }
    // Store initial Path for relative Paths (second argument is reserved)
    $RootPath = (func_num_args() > 1) ? func_get_arg(1) : $Path;
    $RootPathLen = strlen($RootPath);
    // Prepare the array of files
    $Files = array();
    $Iterator = new DirectoryIterator($Path);
    foreach($Iterator as /** @var \SplFileInfo */ $File){
        if($File->isDot()) continue; // Skip . and ..
        if($File->isLink() or (!$File->isDir() and !$File->isFile())) continue; // Skip links & other stuff
        $FilePath = $File->getPathname();
        $RelativePath = str_replace('\\', '/', substr($FilePath, $RootPathLen));
        $Files[$RelativePath] = $FilePath; // Files are string
        if(!$File->isDir()) continue;
        // Calls itself recursively [regardless of name :)]
        $SubFiles = call_user_func(__FUNCTION__, $FilePath, $RootPath);
        $Files[$RelativePath] = $SubFiles; // Folders are arrays
    }
    return $Files; // Return the tree
}

测试其输出并找出问题 :) 你可以做到!


我有点迷惑你的解释 :) - Ben G
@BenG 现在试试吧,这是我能给你的最多了 :) 其余的必须自己学习。 - CodeAngry

0

如果你想获取带有子目录的文件列表,请使用以下代码(但要更改文件夹名称)

<?php
$path = realpath('yourfold/samplefolder');
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename)
{
        echo "$filename\n";
}
?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接