Есть несколько разных способов сделать что-то вроде этого, я дам вам два быстрых подхода на выбор: быстрый и грязный, более длинный и менее грязный (хотя сегодня вечером пятница, поэтому мы позволил немного сойти с ума).
1. Быстрый (и грязный)
Это включает в себя просто написание регулярного выражения (может быть разбито на несколько) для использования для фильтрации коллекции файлов одним быстрым движением.
(Только две закомментированные строки действительно важны для концепции.)
$directory = new RecursiveDirectoryIterator(__DIR__);
$flattened = new RecursiveIteratorIterator($directory);
// Make sure the path does not contain "/.Trash*" folders and ends eith a .php or .html file
$files = new RegexIterator($flattened, '#^(?:[A-Z]:)?(?:/(?!\.Trash)[^/]+)+/[^/]+\.(?:php|html)$#Di');
foreach($files as $file) {
echo $file . PHP_EOL;
}
У этого подхода есть ряд проблем, хотя его легко реализовать, будучи всего лишь одной строкой (хотя регулярное выражение может быть трудной для расшифровки).
2. Менее быстро (и менее грязно)
Более подходящим способом повторного использования является создание пары сделанных на заказ фильтров (с использованием регулярных выражений или чего угодно!), Чтобы сократить список доступных элементов в начальном RecursiveDirectoryIterator
до тех, которые вам нужны. Ниже приведен только один пример, написанный быстро для вас, по расширению RecursiveRegexIterator
.
Мы начнем с базового класса, основной задачей которого является удержание регулярного выражения, с которым мы хотим фильтровать, все остальное откладывается до RecursiveRegexIterator
. Обратите внимание, что класс abstract
, так как он на самом деле не делает ничего полезного: фактическая фильтрация выполняется двумя классами, которые расширяют этот класс. Кроме того, его можно назвать FilesystemRegexFilter
, но ничто не заставляет его (на этом уровне) фильтровать классы, связанные с файловой системой (я бы выбрал лучшее имя, если бы не был таким сонным).
abstract class FilesystemRegexFilter extends RecursiveRegexIterator {
protected $regex;
public function __construct(RecursiveIterator $it, $regex) {
$this->regex = $regex;
parent::__construct($it, $regex);
}
}
Эти два класса являются очень простыми фильтрами, действующими на имя файла и имя каталога соответственно.
class FilenameFilter extends FilesystemRegexFilter {
// Filter files against the regex
public function accept() {
return ( ! $this->isFile() || preg_match($this->regex, $this->getFilename()));
}
}
class DirnameFilter extends FilesystemRegexFilter {
// Filter directories against the regex
public function accept() {
return ( ! $this->isDir() || preg_match($this->regex, $this->getFilename()));
}
}
Чтобы применить это на практике, следующее рекурсивно перебирает содержимое каталога, в котором находится скрипт (не стесняйтесь редактировать это!), И отфильтровывает папки .Trash
(следя за тем, чтобы имена папок сопоставьте со специально созданным регулярным выражением) и принимайте только файлы PHP и HTML.
$directory = new RecursiveDirectoryIterator(__DIR__);
// Filter out ".Trash*" folders
$filter = new DirnameFilter($directory, '/^(?!\.Trash)/');
// Filter PHP/HTML files
$filter = new FilenameFilter($filter, '/\.(?:php|html)$/');
foreach(new RecursiveIteratorIterator($filter) as $file) {
echo $file . PHP_EOL;
}
Особо следует отметить, что, поскольку наши фильтры рекурсивны, мы можем выбрать способ их перебора. Например, мы могли бы легко ограничиться сканированием до 2-х уровней глубиной (включая начальную папку), выполнив:
$files = new RecursiveIteratorIterator($filter);
$files->setMaxDepth(1); // Two levels, the parameter is zero-based.
foreach($files as $file) {
echo $file . PHP_EOL;
}
Также очень легко добавить еще несколько фильтров (путем создания экземпляров наших классов фильтрации с различными регулярными выражениями или путем создания новых классов фильтрации) для более специализированных потребностей фильтрации (например, размер файла, длина полного пути и т. Д.) .).
P.S. Хм, этот ответ немного болтает; Я старался держать его как можно более кратким (даже удаляя огромные полосы супер-болтовни). Извиняюсь, если чистый результат оставляет ответ бессвязным.