【问题标题】:SplRecurisveDirectoryIterator & hierarchical arraySplRecurisveDirectoryIterator & 分层数组
【发布时间】:2012-10-20 06:57:40
【问题描述】:

我想玩弄一些 PHP 的迭代器,并设法得到一个可靠的(根据我的理解)构建。我的目标是在父文件夹中迭代并关闭 2 个节点;在此过程中构建层次树数组。显然,我可以使用 glob 和几个嵌套循环来相当容易地做到这一点,但我想使用 Spl 类来实现这一点。

所有这些,我已经使用了 SplHeap 和 SplObjectStore 来进行层次结构并失败了。我的面条有什么问题是我的正常递归方法失败了(内存不足错误),而我的一个成功在于一种递归方法,该方法循环遍历每个节点,添加到数组中。这样做的问题是它忽略了 setMaxDepth() 方法并遍历了所有的孩子。我想过设置一个 $var++ 来增加循环,限制节点,但我不相信这是“正确的方法”。

任何人,代码(抱歉,如果有任何孤立代码 - 请忽略它)...

<?php
namespace Tree;

use RecursiveFilterIterator,
    RecursiveDirectoryIterator,
    RecursiveIteratorIterator;

class Filter extends RecursiveFilterIterator {
    public static $FILTERS = array(
        '.git', '.gitattributes', '.gitignore', 'index.php'
    );

    public function accept() {
        if (!$this->isDot() && !in_array($this->current()->getFilename(), self::$FILTERS))
            return TRUE;

        return FALSE;
    }
}

class DirTree {
    const MAX_DEPTH = 2;

    private static $iterator;
    private static $objectStore;

    public function __construct() {

        error_reporting(8191);
        $path       = realpath('./');

        try {

            $dirItr     = new RecursiveDirectoryIterator($path);
            $filterItr  = new Filter($dirItr);
            $objects    = new RecursiveIteratorIterator($filterItr, RecursiveIteratorIterator::SELF_FIRST);

            $objects->setMaxDepth(self::MAX_DEPTH);

            echo '<pre>';
            print_r($this->build_hierarchy($objects));

        } catch(Exception $e) {
            die($e->getMessage());
        }
    }

    public function build_hierarchy($iterator){
        $array = array();
        foreach ($iterator as $fileinfo) {

            if ($fileinfo->isDir()) {
                // Directories and files have labels
                $current = array(
                    'label' => $fileinfo->getFilename()
                );
                // Only directories have children
                if ($fileinfo->isDir()) {
                    $current['children'] = $this->build_hierarchy($iterator->getChildren());
                }
                // Append the current item to this level
                $array[] = $current;
            }
        }
        return $array;
    }
}

$d = new DirTree;

【问题讨论】:

    标签: php hierarchical-data spl


    【解决方案1】:

    RecursiveIteratorIterator 的主要目的是为您提供一个迭代器,其行为类似于平面列表上的迭代器,但平面列表实际上只是递归遍历中的一个序列。它通过在内部管理 RecursiveIterators 堆栈来实现这一点,必要时在它们上调用getChildren()。 RecursiveIteratorIterator 的客户端实际上只应该调用普通的Iterator 方法,如current()next() 等...除了像setMaxDepth() 这样的增值方法

    您的问题是您尝试通过调用getChildren() 自己进行递归。如果您想手动管理递归,那很好 - 但这会使 RecursiveIteratorIterator 变得多余。事实上,我真的很惊讶在RecursiveIteratorIterator 上调用getChildren() 并没有致命错误。那是RecursiveIterator 方法。 spl 可能只是将方法调用转发给内部迭代器(一些 spl 类将方法调用转发给未定义的方法,以便于使用装饰器设计模式)。

    正确的方法:

        $dirItr     = new RecursiveDirectoryIterator($path);
        $filterItr  = new Filter($dirItr);
        $objects    = new RecursiveIteratorIterator($filterItr, RecursiveIteratorIterator::SELF_FIRST);
    
        $objects->setMaxDepth(self::MAX_DEPTH);
    
        echo '<pre>';
        foreach ($objects as $splFileInfo) {
            echo $splFileInfo;
            echo "\n";
        }
    

    我不打算为您以某种特定结构形成分层数组,但也许这个相关问题可以进一步帮助您理解RecursiveIteratorIteratorRecursiveIterator 之间的区别 How does RecursiveIteratorIterator work in PHP?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多