В данном уроке мы разберемся с типовой задачей, которая возникает во время работы над проектом PHP: получение списка файлов и директорий. Обсудим несколько базовых и более изощренных подходов, с перечисление плюсов и минусов каждого. Первые три решения будут использовать типовые функции PHP, а затем представим более надежное с применением итераторов SPL.
Для предметного обсуждения решения и демонстраций предположим, что структура директорий имеет следующий вид:
—manager | —user | —document.txt | —data.dat | —style.css |—article.txt |—master.dat |—script.php |—test.dat |—text.txt
Базовые решения
Первый набор решений основан на использовании функции glob(), комбинации функций opendir(), readdir() и closedir(), и также функции scandir().
Использование glob()
Первое решение базируется на использовании функции glob(), которая позволяет выполнять поиск пути с помощью шаблонов. Функция имеет два параметра:
Рассмотрим примеры. Для поиска в директории всех файлов и директорий, имена которых заканчиваются на .txt, следует использовать код:
<?php $filelist = glob(«*.txt»);
Если вывести переменную $filelist, то получим:
array ( 0 => ‘article.txt’, 1 => ‘text.txt’ )
Если нужен список файлов и директорий, имена которых начинаются на “te”, то код будет выглядеть так:
<?php $filelist = glob(«te*»);
А вывод имеет вид:
array ( 0 => ‘test.dat’, 1 => ‘text.txt’ )
А для получения списка только директорий с именами, содержащих “ma”, используем код:
<?php $filelist = glob(«*ma*», GLOB_ONLYDIR);
Последний пример выведет:
Обратите внимание, что в последнем примере использован флаг GLOB_ONLYDIR в качестве второго параметра функции. Поэтому файл master.dat исключен из списка. Хотя функция glob() очень проста в использовании, иногда она недостаточно гибкая. Например, нет флага для получения только файлов (без директорий), которые соответствуют шаблону.
Используем opendir(), readdir(), и closedir().
Второй подход к получению списка файлов и директорий, который мы обсудим, заключается в использовании функций opendir(), readdir(), и closedir().
Функция opendir() открывает директорию и возвращает дескриптор соединения. Как только дескриптор получен, можно использовать функцию readdir(). С каждым обращением данная функция выдает имя следующего файла или директории внутри открытого каталога. Если все имена уже были перечислены, функция возвращает false. Для закрытия дескриптора используется функция closedir().
В отличие от использования функции glob(), данный подход сложнее, так как у вас нет параметров, которые помогают фильтровать список возвращаемых имен файлов и директорий. Вы должны выполнить фильтрацию самостоятельно, чтобы получить нужный результат.
Ниже приведенный пример возвращает список имен файлов и директорий начинающихся на “te”:
<?php $filelist = array(); if ($handle = opendir(«.»)) { while ($entry = readdir($handle)) { if (strpos($entry, «te») === 0) { $filelist[] = $entry; } } closedir($handle); }
При выполнении выше приведенного кода, переменная $entry будет содержать такие включения, как “.” и “..”. Это две виртуальные директории, которые имеются в каждом каталоге файловой системы. Они представляют текущий каталог и родительский каталог соответственно.
Второй пример выводит только файлы, содержащиеся в заданном каталоге.
<?php $filelist = array(); if ($handle = opendir(«.»)) { while ($entry = readdir($handle)) { if (is_file($entry)) { $filelist[] = $entry; } } closedir($handle); }
Пример выдаст следующее:
array ( 0 => ‘article.txt’, 1 => ‘master.dat’, 2 => ‘script.php’, 3 => ‘test.dat’, 4 => ‘text.txt’ )
Использование scandir()
В завершение представим функцию scandir(). Она имеет только один обязательный параметр: путь для чтения. Функция возвращает массив фалов и директорий, расположенных по указанному пути. Для получения списка файлов и директорий по определенному критерию нужно выполнить дополнительную фильтрацию. С другой стороны, решение получается более кратким и не требует управления дескрипторами.
Данный пример показывает, как получить список фалов и каталогов, имена которых начинаются на “te”:
<?php $entries = scandir(«.»); $filelist = array(); foreach($entries as $entry) { if (strpos($entry, «te») === 0) { $filelist[] = $entry; } }
Воспользуемся итераторами SPL
Теперь рассмотрим использование итераторов SPL. Но прежде, чем приступить к решению нашей задачи, проведем введение в библиотеку SPL и итераторы. Библиотека SPL предоставляет серию классов для объектно ориентированных структур данных, итераторов, дескрипторов фалов и прочее.
Одно из преимуществ итераторов заключается в том, что они являются классами и их можно расширить для удовлетворения собственных нужд. Другой плюс состоит в том, что итераторы имеют собственные методы, которые являются полезными при решении множества типовых задач и располагаются в одном месте. Посмотрите на пример использования FilesystemIterator в сравнении с readdir(). Оба метода применяют цикл, но в случае readdir() вы обрабатываете только строку, а FilesystemIterator работает с объектом, который может содержать дополнительную информацию о файле или директории (размер, владелец, права доступа и так далее).
Конечно, PHP представляет возможность для получения такой информации с помощью функций,например filesize() и fileowner(). Но PHP5 основан на использовании концепции ООП. Поэтому лучше использовать современные методы работы с языком программирования. На нашем сайте есть уроки, посвященные работе с итераторами.
Как уже сообщалось во водной части урока, мы рассмотрим использование FilesystemIterator, RecursiveDirectoryIterator и GlobIterator. Первый наследуется от DirectoryIterator, а остальные от FilesystemIterator. Они все имеют один и тот же конструктор, который принимает два параметра:
Реальное различие в данных итераторах заключается в их использовании для навигации по заданному пути.
FilesystemIterator
Использовать FilesystemIterator очень просто. Рассмотрим в действии. Представляем два примера. Первый показывает поиск всех файлов и каталогов, имена которых начинаются на “te”. Второй пример использует другой итератор RegexIterator для поиска всех фалов и каталогов, имена которых заканчиваются на “t.dat” или “t.php”. Итератор RegexIterator используется для фильтрации результата на основе регулярных выражений.
<?php $iterator = new FilesystemIterator(«.»); $filelist = array(); foreach($iterator as $entry) { if (strpos($entry->getFilename(), «te») === 0) { $filelist[] = $entry->getFilename(); } }
Выше приведенный код выдаст результат, аналогичный предыдущим примерам.
Второй пример с применением RegexIterator:
<?php $iterator = new FilesystemIterator(«.»); $filter = new RegexIterator($iterator, ‘/t.(php|dat)$/’); $filelist = array(); foreach($filter as $entry) { $filelist[] = $entry->getFilename(); }
Он будет выводить:
array ( 0 => ‘script.php’, 1 => ‘test.dat’ )
RecursiveDirectoryIterator
Итератор RecursiveDirectoryIterator обеспечивает интерфейс для рекурсивного прохода по директориям файловой системы. Он имеет несколько полезных методов, таких как getChildren() и hasChildren(), которые возвращают итератор для текущего места, если это директория, и проверяют, является ли текущая точка входа директорией. Следующий пример демонстрирует использование RecursiveDirectoryIterator и getChildren(). Результат будет такой же, как и в предыдущих примерах.
<?php $iterator = new RecursiveDirectoryIterator(‘.’); $filter = new RegexIterator($iterator->getChildren(), ‘/t.(php|dat)$/’); $filelist = array(); foreach($filter as $entry) { $filelist[] = $entry->getFilename(); }
GlobIterator
Итератор GlobIterator выполняет проход по файловой системе также, как и функция glob(). Первый параметр может включать шаблон для имени. Пример демонстрирует использование GlobIterator с тем же результатом, что и ранее.
<?php $iterator = new GlobIterator(«te*»); $filelist = array(); foreach($iterator as $entry) { $filelist[] = $entry->getFilename(); }
Заключение
В данном уроке демонстрируется использование различных подходов для достижение одинаковой цели: получение списка файлов и директорий. Следует запомнить следующие ключевые моменты:
Источник: http://feedproxy.google.com/~r/ruseller/CdHX/~3/fWQpdbbOVDY/lessons.php
Источник: