В старых версиях PHP для работы с файлами и каталогами предусмотрены такие функции как open_dir, read_dir и т.д. Начиная с 5-ой версии PHP для работы с файловой структурой намного удобнее использовать классы (). Для наглядности предлагаю разобрать небольшой пример.
Допустим, нам необходимо просканировать дерево каталогов и найти в них все файлы. Затем полученный список нужно отсортировать в алфавитном порядке. Вот как эту задачу можно решить используя SPL:
$dirTree = new RecursiveDirectoryIterator("./testDir");
$sortedFileList = new FileSorterIterator(new RecursiveItertatorIterator($dirTree));
foreach($sortedFileList as $file) {
echo $file->getFilename() . '<br />';
}
class FileSorterIterator extends SplHeap
{
public function __constructor(Iterator $iterator) {
foreach ($iterator as $item) {
if ($item->isFile()) {
// отсеиваем директории,
// так как в условиях нашей задачи нужно получить только список файлов
$this->insert($item);
}
}
}
public function compare($b,$a)
{
return strcmp($a->getFilename(), $b->getFilename());
}
}
Как видите, пример получился очень простым. Если в старых версиях PHP приходилось самостоятельно отслеживать указатель на открытую директорию и своевременно его закрывать, то теперь всю «грязную» работу берут на себя классы SPL.
Теперь давайте разберемся какие классы SPL используются в примере:
Класс RecursiveDirectoryIterator
RecursiveDirectoryIterator — это класс SPL который рекурсивно просматривает заданную директорию и составляет дерево всех файлов и директорий. При создании класса нужно указать директорию в которой должен осуществляться поиск.
Для того, чтобы работать с построенным деревом используются стандартные функции интерфейса , а так же несколько .
При работе с данным классом нужно помнить, что функции на подобие foreach перебирают только элементы файловой структуры, находящиеся в корне построенного дерева. Для того, чтобы перебрать элементы расположенные ниже по структуре (имеются в виду вложенные директории) следует использовать специальный класс RecursiveIteratorIterator.
Класс RecursiveIteratorIterator
RecuriveIteratorIterator — это класс созданный для последовательно перебора элементов древовидных итераторов. В нашем примере данный класс используется для того, чтобы обработать файлы расположенные в поддиректориях корневой директории.
Класс FileSorterIterator
FileSorterIterator — это пользовательский класс созданный на базе класса . Данный класс нужен для того, чтобы отсортировать файлы в алфавитном порядке. Для этого, используется функция compare, которая содержит условие сортировки, исходя из которого и определяется место элемента в общем массиве.
Исключительные ситуации
Теперь, хочется пару слов сказать о том, что делать если в результате работы указанных классов возникает какая-то ошибка. Например, мы указали для сканирования несуществующую директорию:
$dirTree = new RecursiveDirectoryIterator("./noneExistDirectory");
При возникновении ошибки в работе SPL классов генерируется соответствующее исключение, в случае если эти исключения не обрабатываются, они приводят к останову работы программы в целом. Поэтому лучше предусмотреть обработку наиболее вероятных исключительных ситуаций в программе.
Исключительные ситуации обрабатываются следующим образом:
try{
$dirTree = new RecursiveDirectoryIterator("./testDasdfsdf");
}catch(Exception $e) {
var_dump($e->getMessage());
}
В примере вся обработка сводится к выводу сообщения о полученном исключении на экран — RecursiveDirectoryIterator::__construct(./testDasdfsdf): failed to open dir: No such file or directory. В реальном приложении такая обработка, естественно, не подходит, поэтому вместо вывода сообщений на экран стоит придумать, что-то посерьезнее.