Creating a new Iterator from the results of another Iterator

I am trying to use Iterators efficiently in PHP 5, and without a lot of decent examples on the web, this proves to be a bit complicated.

I am trying to iterate over a directory and read all (php) files inside to search for specific classes. What I want to do then is to have an associative array returned with class names as keys, file path as values.

Using RecursiveDirectoryIterator (), I can recurs through directories. By passing this to the RecursiveIteratorIterator, I can get the contents of the directory as a one-dimensional iterator. By then, using a filter on this, I can filter out all directories and non-php files that will just leave me the files that I want to consider.

What I want to do now is pass this iterator to another iterator (not sure which one will be suitable), so when iterates over each record, it can get an array that needs to be combined into a master array.

A bit hard to explain, so here is a sample code:

// $php_files now represents an array of SplFileInfo objects representing files under $dir that match our criteria
$php_files = new PhpFileFilter(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)));

class ClassDetector extends FilterIterator {
    public function accept() {
        $file = $this->current(); // get the current item, which will be an SplFileInfo object

        // Match all the classes contained within this file
        if (preg_match($regex, $file->getContents(), $match)) {
            // Return an assoc array of all the classes matched, the class name as key and the filepath as value
            return array(
                'class1' => $file->getFilename(),
                'class2' => $file->getFilename(),
                'class3' => $file->getFilename(),
            );
        }
    }
}

foreach (new ClassDetector($php_files) as $class => $file) {
    print "{$class} => {$file}\n";
}

// Expected output:
// class1 => /foo.php
// class2 => /foo.php
// class3 => /foo.php
// class4 => /bar.php
// class5 => /bar.php
// ... etc ...

As you can see from this example, I kind of grabbed the accept () method for FilterIterator, which is a completely incorrect use that I know, but I use it only as an example to demonstrate how I just need one function to call and to return an array that is combined into the main array.

, RecursionIterators, , , (hasChildren() getChildren()) .

, , Iterator ( ), (?) .

, : ala - :

$master = array();
foreach($php_files as $file) {
    if (preg_match($regex, $file->getContents(), $match)) {
        // create $match_results
        $master = array_merge($master, $match_results);
    }
}

, .

, , . :)

+3
2

, . , , IteratorIterator, , Iterator.

, , . , SplFileInfo ( DirectoryIterator).

class
    ClassMatcher
extends
    IteratorIterator
implements
    RecursiveIterator
{

    protected $matches;

    public function hasChildren() {
        return preg_match_all(
            '#class (\w+)\b#ism',
            file_get_contents($this->current()->getPathname()),
            $this->matches
        );
    }

    public function getChildren() {
        $classes = $this->matches[1];

        return new RecursiveArrayIterator(
            array_combine(
                $classes,                                                       // class name as key
                array_fill(0, count($classes), $this->current()->getPathname()) // file path as value
            )
        );
    }
}
+1

- - . , , . - , , .

- SplFileInfo, RecursiveIteratorIterator:: setInfoClass ($ className);, . PHP , .

0

Source: https://habr.com/ru/post/1703649/


All Articles