【问题标题】:Array with all sub-folders and files alphabetically while retaining structure在保留结构的同时按字母顺序排列所有子文件夹和文件
【发布时间】:2021-07-14 18:56:52
【问题描述】:

概览

我们正在构建一个基于 PHP 的模板引擎(我知道是原创的)。核心功能之一是模板列表页面,用户可以在其中查看其用户定义的模板并使用它们创建页面对象。这些文件存储在 html 文件或 SQL 存储系统中。

我们已经完成了模板引擎中文件的加载,SQL 轻而易举,现在我们正在尝试自己加载 html 文件以供用户解析和列出。

代码

我们正在使用以下代码来获取目录中所有文件及其子文件的列表,然后将它们添加到数组中。

function get_directory_contents($directory, $hide_index_files = TRUE, $limit_to_html_files = TRUE) {
    $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS));
    $files = array(); 
    foreach ($rii as $file) {
        if ($file->isDir()){ 
            $files['directories'][] = $file;
        } else {
            if ($hide_index_files) {
                if ($file->getFilename() == "index.html") {
                    continue;
                }
            }
            if ($limit_to_html_files) {
                if (substr($file->getFilename(), -5) != ".html") {
                    continue;
                }
            }
            $count_to_filename = strlen($directory . "/");
            $count_from_filename = strlen($file->getFilename());
            $count_from_filename_plus_one = strlen($file->getFilename()) + 1;
            $file_path_full = substr($file->getPathname(), $count_to_filename);
            $remove_name = -1 * abs($count_from_filename_plus_one);
            $file_path = substr($file_path_full, 0, $remove_name);
            if (!$file_path) {
                $file_path = "base_directory";
            }
            $files['files'][] = array("fullpath" => $file_path_full, "justPath" => $file_path, "filename" => $file->getFilename());
        }
    }
    return $files;
}

路径指向模板中名为 templates/user-defined 的子文件夹,启用 RecursiveDirectoryIterator::SKIP_DOTS 标志后,files[directories] 字段返回空 - 当前代码返回以下数组:

Array
(
    [files] => Array
        (
            [0] => Array
                (
                    [fullpath] => hello_world.html
                    [justPath] => base_directory
                    [filename] => hello_world.html
                )
            [1] => Array
                (
                    [fullpath] => another_folder/file.html
                    [justPath] => another_folder
                    [filename] => file.html
                )
            [2] => Array
                (
                    [fullpath] => second_folder/alpha_file.html
                    [justPath] => second_folder
                    [filename] => alpha_file.html
                )
            [3] => Array
                (
                    [fullpath] => second_folder/bravo_file.html
                    [justPath] => second_folder
                    [filename] => bravo_file.html
                )
        )
)

所需输出

我们希望看到按字母顺序输出的数组列表,并保持文件夹结构完整。目前,我们使用的 RecursiveDirectoryIterator 按文件上次编辑时间对条目进行排序,然后我们调用 asort() 尝试按字母顺序对项目进行排序,但它也不保留目录架构。

理想情况下,我们希望支持空文件夹并在其下列出其子文件夹,同时返回如下所示的数组:

Array
(
    [files] => Array
        (
            [another_folder] => Array
                (
                    [0] => Array
                        (
                            [fullpath] => another_folder/file.html
                            [filename] => file.html
                        )
                )
            [empty_folder] => Array
                (
                )
            [second_folder] => Array
                (
                    [0] => Array
                        (
                            [fullpath] => second_folder/file.html
                            [filename] => file.html
                        )
                    [1] => Array
                        (
                            [fullpath] => second_folder/bravo_file.html
                            [filename] => file.html
                        )
                )
            [base_directory] => Array
                (
                    [0] => Array
                        (
                            [fullpath] => hello_world.html
                            [filename] => hello_world.html
                        )
                )
        )
)

这将允许我们像这样列出它们:

/another_folder/
-> file.html

/empty_folder/

/second_folder/
-> alpha_file.html
-> bravo_file.html

/
-> hello_world.html

我们正在使用 RecursiveDirectoryIterator()RecursiveIterator() 函数,因为它们被认为比简单的 scandir 更快,并且它们具有我们更喜欢的良好对象方法。

我们如何在保持快速加载的同时实现这一点?

【问题讨论】:

    标签: php file


    【解决方案1】:

    我决定使用scandir() 函数并创建了一个递归函数,您可以输入初始路径和路径长度,如下所示:

    $template_path = "/templates/user-defined";
    $count_to_filename = strlen(dirname(dirname(__FILE__)) . $template_path . "/");
    $list_of_templates_html = map_directory_contents(dirname(dirname(__FILE__)) . $template_path, $count_to_filename);
    
    
    function map_directory_contents($directory, $count, $depth = 0, $base_directory = TRUE, $hide_index_files = TRUE, $limit_to_html_files = TRUE) {
        global $templates;
        $folder_data = array();
        $file_data = array();
        $current_depth = $depth - 1;
        $directory = rtrim($directory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
        $files = array_slice(scandir($directory), 2);
        foreach ($files as $key => $file) {
            if (($directory . $file == __FILE__) || (substr($file, 0, 1) === '.')) {
                continue;
            }
            $this_path = str_replace(__DIR__ . DIRECTORY_SEPARATOR, '', $directory . $file);
            if (($depth < 1 OR $current_depth > 0) && is_dir($directory . $file)) {
                $folder_data[$file] = array("fullpath" => $this_path, "type" => "folder", "name" => $file, "files" => map_directory_contents($directory . $file, $count, $current_depth, FALSE, $hide_index_files, $limit_to_html_files));
            } else {
                if ($limit_to_html_files) {
                    if (substr($file, -5) != ".html") {
                        continue;
                    }
                }
                if ($hide_index_files) {
                    if ($file == "index.html") {
                        continue;
                    }
                }
                if ($base_directory) {
                    if(!isset($file_data["base_directory"]["type"])) {
                        $file_data["base_directory"]["fullpath"] = rtrim($directory, DIRECTORY_SEPARATOR);
                        $file_data["base_directory"]["type"] = "folder";
                        $file_data["base_directory"]["name"] = "/";
                    }
                    $file_data["base_directory"]["files"][] = array("fullpath" => $this_path, "nonce_id" => $templates->nonce_id, "path" => substr($this_path, $count), "type" => "file", "editable" => (is_writable($this_path) ? TRUE : FALSE), "name" => $file);
                } else {
                    $file_data[] = array("fullpath" => $this_path, "nonce_id" => $templates->nonce_id, "path" => substr($this_path, $count), "type" => "file", "editable" => (is_writable($this_path) ? TRUE : FALSE), "name" => $file);
                }
                $templates->nonce_id++;
            }
        }
        !empty($folder_data) ? ksort($folder_data) : false;
        $map_data = array_merge($folder_data, $file_data);
        return $map_data;
    }
    

    这样做会返回以下数组:

    Array
    (
        [another_folder] => Array
            (
                [fullpath] => /home/public_html/templates/user-defined/another_folder
                [type] => folder
                [name] => another_folder
                [files] => Array
                    (
                        [0] => Array
                            (
                                [fullpath] => /home/public_html/templates/user-defined/another_folder/file.html
                                [path] => another_folder/file.html
                                [type] => file
                                [editable] => 1
                                [name] => file.html
                            )
                    )
            )
        [empty_folder] => Array
            (
                [fullpath] => /home/public_html/templates/user-defined/empty_folder
                [type] => folder
                [name] => empty_folder
                [files] => Array
                    (
                    )
            )
        [second_folder] => Array
            (
                [fullpath] => /home/public_html/templates/user-defined/second_folder
                [type] => folder
                [name] => second_folder
                [files] => Array
                    (
                        [0] => Array
                            (
                                [fullpath] => /home/public_html/templates/user-defined/second_folder/alpha_file.html
                                [path] => second_folder/alpha_file.html
                                [type] => file
                                [editable] => 1
                                [name] => alpha_file.html
                            )
                        [1] => Array
                            (
                                [fullpath] => /home/public_html/templates/user-defined/second_folder/bravo_file.html
                                [path] => second_folder/bravo_file.html
                                [type] => file
                                [editable] => 1
                                [name] => bravo_file.html
                            )
                    )
            )
        [base_directory] => Array
            (
                [fullpath] => /home/public_html/templates/user-defined/hello_world.html
                [path] => hello_world.html
                [type] => file
                [editable] => 1
                [name] => hello_world.html
            )
    )
    

    如您所见,我已经删除了 base_directory 键,然后在最后重新添加它,这样它(理论上)总是会在其他目录之后列出 BASE 文件。

    【讨论】:

      猜你喜欢
      • 2010-11-08
      • 1970-01-01
      • 1970-01-01
      • 2014-08-15
      • 2018-06-13
      • 1970-01-01
      • 1970-01-01
      • 2022-06-29
      • 1970-01-01
      相关资源
      最近更新 更多