В чем преимущество использования итераторов SPL при обходе файловой системы?

Я провел немало исследований и пришел к выводу, что лучше всего реализовать все с помощью старого scandir а также foreach вместо того, чтобы идти по пути итератора.

По сути, мне нужен способ получения содержимого каталогов — опционально отсортированный, опционально рекурсивный и опционально отфильтрованный по имени файла. Какая IMO — самая базовая функциональность, которую вы ожидаете от любого довольно сложного обходчика файловой системы.

Ну так получается, ни RecursiveDirectoryIterator ни FilesystemIterator поддержка сортировки или же фильтрация. Нужно обернуть их в классе, который расширяет ArrayObject добиться сортировки — или FilterIterator для фильтрации. Так что для достижения обоих нужно написать два классы, упаковывающие все в несметное число уровней, и код в конечном итоге выглядит странным и слишком сложным.

Я что-то упускаю из-за подхода, или я должен поцарапать свой прогресс и переписать все в 20+ строк в простой тупой if/else/foreach код?

0

Решение

Итераторы, найденные в SPL, не все «готовы к работе». Это базовые блоки, которые можно использовать для создания чего угодно. FileSystemIterator может иметь некоторую базовую функциональность для фильтрации, но вы хотите создать больше самостоятельно, и это довольно легко сделать.

Преимущество использования итераторов, таких как FilesystemIterator и таково то, что вы отделяете логику обхода от логики фильтра от логики сортировки от бизнес-логики.

Скажем, у вас есть следующее:

$dir = opendir('.');
while (($file = readdir($dir)) !== false) {
// business logic
}

и позже вы решите фильтровать только файлы MP3:

$dir = opendir('.');
while (($file = readdir($dir)) !== false) {
if (preg_match('|\.mp3$|i', $file)) {
// business logic
}
}

Но как насчет фильтрации файлов MP3 и JPG или файлов MP3, размер которых меньше 5 МБ, и всего недельной давности, и файлов JPG, размер которых превышает 2 МБ, а как насчет нескольких каталогов или рекурсивных каталогов и т. Д.? Ваша петля «foreach / while» становится кошмаром, хотя все начиналось довольно мило.

Отделение логики обхода от бизнес-логики означает, что ее проще поддерживать, тестировать и даже повторно использовать:

$it = new DirectoryIterator(".");      // Dir iterator
$it = new RegexIterator($it, "|\.mp3$|i");  // filter MP3's
$it = new FilesizeIterator($it, "<6MB");  // Only less than 6MB
$it = new LimitIterator($it, 0, 100);   // First 100 items only

foreach ($it as $file) {
// extrabonus: $file is a SplFileInfo object
}

Легко представить, как мы могли бы «встроить» логику итератора в более сложные примеры, и мы можем использовать такие вещи, как RegexIterator для других вещей, кроме имен файлов тоже. Это также намного легче проверить, потому что нам нужно только проверить, regexFilterIterator правильно фильтрует регулярные выражения, вот и все.

Сортировка и тому подобное также могут быть добавлены, основываясь на том, что вам нравится, но все же: никаких изменений в вашей бизнес-логике, и при этом все еще оторвано от всей другой логики.

Взгляните на Symfony2 Finder Компонент: он использует много итераторов для фильтрации и сортировки элементов.

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]