How to ignore directories using RecursiveIteratorIterator?

iterator, php

Solution

Your `DirFilter` wants to extend `RecursiveFilterIterator`, since it is being used with a recursive iterator. Not doing that, is the cause of your error.

class DirFilter extends RecursiveFilterIterator
{
    // …
}

The next step is figuring out how to use `accept()` properly. It is supposed to return a `true` or `false` value, which dictates whether the current item should be included (`true`) or excluded (`false`) from the iteration. Returning a file name from `accept()` is not what you want to be doing.

class DirFilter extends RecursiveFilterIterator
{
    public function accept()
    {
        $excludes = array("cache", "cache2");
        return !($this->isDir() && in_array($this->getFilename(), $excludes));
    }
}

It might be nice to be able to pass in the array of excluded directories. This requires a little more code but is much more reusable.

class DirFilter extends RecursiveFilterIterator
{
    protected $exclude;
    public function __construct($iterator, array $exclude)
    {
        parent::__construct($iterator);
        $this->exclude = $exclude;
    }
    public function accept()
    {
        return !($this->isDir() && in_array($this->getFilename(), $this->exclude));
    }
    public function getChildren()
    {
        return new DirFilter($this->getInnerIterator()->getChildren(), $this->exclude);
    }
}

This code could then be used like:

$directory = new RecursiveDirectoryIterator($dirname);
$filtered = new DirFilter($directory, $dirignore); 
$mega = new RecursiveIteratorIterator($filtered, …);

Problem

I have tried several methods to ignore certain directories using `RecursiveIteratorIterator` on a file system. For the sake of an example say I want to ignore the following directory: `/cache`. My `Iterator` looks like this: ``` //$dirname is root $directory = new RecursiveDirectoryIterator($dirname); $mega = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); foreach ($mega as $fileinfo) { echo $fileinfo; } ``` I have been able to ignore certain file extensions using `pathinfo` for example this works: ``` $filetypes = array("jpg", "png"); $filetype = pathinfo($fileinfo, PATHINFO_EXTENSION); foreach ($mega as $fileinfo) { if (!in_array(strtolower($filetype), $filetypes)) { echo $fileinfo; } } ``` When I try it using `PATHINFO_DIRNAME` (with the appropriate directory paths in the array) it does not work, there are no errors, it just does not ignore the directories. I have also experimented with using `FilterIterator` to no avail, and now I'm thinking maybe I should use `RegexIterator`. What would be the simplest and most efficient way to ignore directories using `RecursiveIteratorIterator` ? Experiments that didn't work. Using `PATHINFO_DIRNAME` ``` $dirignore = array("cache", "cache2"); $directory = new RecursiveDirectoryIterator($dirname); $mega = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); $dirtype = pathinfo($fileinfo, PATHINFO_DIRNAME); if (!in_array($dirtype), $dirignore)) { echo $fileinfo; //no worky still echo directories } ``` Using `FilterIterator` (not sure how this works) ``` class DirFilter extends FilterIterator { public function accept() { //return parent::current() != "..\cache\"; $file = $this->getInnerIterator()->current(); if ($file != "..\cache") return $file->getFilename(); //also tried with same error as below //return !preg_match('/\cache', $file->getFilename()); } } $directory= new RecursiveDirectoryIterator($dirname); $directory = new DirFilter($directory); $mega = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); // loop ``` Tis results in `Error: An instance of RecursiveIterator or IteratorAggregate creating it is required`

Original source