Я попытался несколько методов игнорировать некоторые каталоги, используя RecursiveIteratorIterator
в файловой системе.
Для примера скажем, я хочу игнорировать следующий каталог: /cache
.
Мой Iterator
выглядит так:
//$dirname is root $directory = new RecursiveDirectoryIterator($dirname); $mega = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); foreach ($mega as $fileinfo) { echo $fileinfo; }
Я мог игнорировать некоторые расширения файлов с помощью pathinfo
например, это работает:
$filetypes = array("jpg", "png"); $filetype = pathinfo($fileinfo, PATHINFO_EXTENSION); foreach ($mega as $fileinfo) { if (!in_array(strtolower($filetype), $filetypes)) { echo $fileinfo; } }
Когда я пытаюсь использовать PATHINFO_DIRNAME
(с соответствующими каталогами в массиве), это не работает, ошибок нет, он просто не игнорирует каталоги.
Я также экспериментировал с использованием FilterIterator
безрезультатно, и теперь я думаю, что я должен использовать RegexIterator
.
Каким будет самый простой и эффективный способ игнорировать каталоги с помощью RecursiveIteratorIterator
?
Эксперименты, которые не сработали. Использование 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 }
Использование FilterIterator
(не знаю, как это работает)
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 приводит к Error: An instance of RecursiveIterator or IteratorAggregate creating it is required
Ваш DirFilter
хочет расширить RecursiveFilterIterator
, поскольку он используется с рекурсивным итератором. Не делая этого, является причиной вашей ошибки.
class DirFilter extends RecursiveFilterIterator { // … }
Следующий шаг – выяснить, как правильно использовать accept()
. Он должен возвращать true
или false
значение, которое определяет, должен ли текущий элемент быть включен ( true
) или исключен ( false
) из итерации. Возвращение имени файла из accept()
не является тем, что вы хотите делать.
class DirFilter extends RecursiveFilterIterator { public function accept() { $excludes = array("cache", "cache2"); return !($this->isDir() && in_array($this->getFilename(), $excludes)); } }
Возможно, было бы неплохо пройти в массив исключенных каталогов. Для этого требуется немного больше кода, но он гораздо более многоразовый.
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); } }
Затем этот код можно использовать как:
$directory = new RecursiveDirectoryIterator($dirname); $filtered = new DirFilter($directory, $dirignore); $mega = new RecursiveIteratorIterator($filtered, …);