Все ленты — последние статьи

PHP: список файлов и директорий(много)

PHP: список файлов и директорий

В данном уроке мы разберемся с типовой задачей, которая возникает во время работы над проектом PHP: получение списка файлов и директорий. Обсудим несколько базовых и более изощренных подходов, с перечисление плюсов и минусов каждого. Первые три решения будут использовать типовые функции PHP, а затем представим более надежное с применением итераторов SPL.

Для предметного обсуждения решения и демонстраций предположим, что структура директорий имеет следующий вид:
01 ---manager
02
03 ---user
04 ---document.txt
05 ---data.dat
06 ---style.css
07 ---article.txt
08 ---master.dat
09 ---script.php
10 ---test.dat
11 ---text.txt

 


Базовые решения

Первый набор решений основан на использовании функции glob(), комбинации функций opendir(), readdir() и closedir(), и также функции scandir().


Использование glob()

Первое решение базируется на использовании функции glob(), которая позволяет выполнять поиск пути с помощью шаблонов. Функция имеет два параметра:

$pattern (обязательный): шаблон поиска
$flags (опциональный): один или несколько флагов, описание которых можно найти в документации

Рассмотрим примеры. Для поиска в директории всех файлов и директорий, имена которых заканчиваются на .txt, следует использовать код:
1 <?php
2 $filelist = glob("*.txt");

Если вывести переменную $filelist, то получим:
1 array (
2 0 => 'article.txt',
3 1 => 'text.txt'
4 )

Если нужен список файлов и директорий, имена которых начинаются на “te”, то код будет выглядеть так:
1 <?php
2 $filelist = glob("te*");

А вывод имеет вид:
1 array (
2 0 => 'test.dat',
3 1 => 'text.txt'
4 )

А для получения списка только директорий с именами, содержащих “ma”, используем код:
1 <?php
2 $filelist = glob("*ma*", GLOB_ONLYDIR);

Последний пример выведет:
1 array (
2 0 => 'manager'
3 )

Обратите внимание, что в последнем примере использован флаг GLOB_ONLYDIR в качестве второго параметра функции. Поэтому файл master.dat исключен из списка. Хотя функция glob() очень проста в использовании, иногда она недостаточно гибкая. Например, нет флага для получения только файлов (без директорий), которые соответствуют шаблону.


Используем opendir(), readdir(), и closedir().

Второй подход к получению списка файлов и директорий, который мы обсудим, заключается в использовании функций opendir(), readdir(), и closedir().

Функция opendir() открывает директорию и возвращает дескриптор соединения. Как только дескриптор получен, можно использовать функцию readdir(). С каждым обращением данная функция выдает имя следующего файла или директории внутри открытого каталога. Если все имена уже были перечислены, функция возвращает false. Для закрытия дескриптора используется функция closedir().

В отличие от использования функции glob(), данный подход сложнее, так как у вас нет параметров, которые помогают фильтровать список возвращаемых имен файлов и директорий. Вы должны выполнить фильтрацию самостоятельно, чтобы получить нужный результат.

Ниже приведенный пример возвращает список имен файлов и директорий начинающихся на “te”:
01 <?php
02 $filelist = array();
03 if ($handle = opendir(".")) {
04 while ($entry = readdir($handle)) {
05 if (strpos($entry, "te") === 0) {
06 $filelist[] = $entry;
07 }
08 }
09 closedir($handle);
10 }

При выполнении выше приведенного кода, переменная $entry будет содержать такие включения, как “.” и “..”. Это две виртуальные директории, которые имеются в каждом каталоге файловой системы. Они представляют текущий каталог и родительский каталог соответственно.

Второй пример выводит только файлы, содержащиеся в заданном каталоге.
01 <?php
02 $filelist = array();
03 if ($handle = opendir(".")) {
04 while ($entry = readdir($handle)) {
05 if (is_file($entry)) {
06 $filelist[] = $entry;
07 }
08 }
09 closedir($handle);
10 }

Пример выдаст следующее:
1 array (
2 0 => 'article.txt',
3 1 => 'master.dat',
4 2 => 'script.php',
5 3 => 'test.dat',
6 4 => 'text.txt'
7 )


Использование scandir()

В завершение представим функцию scandir(). Она имеет только один обязательный параметр: путь для чтения. Функция возвращает массив файлов и директорий, расположенных по указанному пути. Для получения списка файлов и директорий по определенному критерию нужно выполнить дополнительную фильтрацию. С другой стороны, решение получается более кратким и не требует управления дескрипторами.

Данный пример показывает, как получить список файлов и каталогов, имена которых начинаются на “te”:
1 <?php
2 $entries = scandir(".");
3 $filelist = array();
4 foreach($entries as $entry) {
5 if (strpos($entry, "te") === 0) {
6 $filelist[] = $entry;
7 }
8 }


Воспользуемся итераторами SPL

Теперь рассмотрим использование итераторов SPL. Но прежде, чем приступить к решению нашей задачи, проведем введение в библиотеку SPL и итераторы. Библиотека SPL предоставляет серию классов для объектно ориентированных структур данных, итераторов, дескрипторов файлов и прочее.

Одно из преимуществ итераторов заключается в том, что они являются классами и их можно расширить для удовлетворения собственных нужд. Другой плюс состоит в том, что итераторы имеют собственные методы, которые являются полезными при решении множества типовых задач и располагаются в одном месте. Посмотрите на пример использования FilesystemIterator в сравнении с readdir(). Оба метода применяют цикл, но в случае readdir() вы обрабатываете только строку, а FilesystemIterator работает с объектом, который может содержать дополнительную информацию о файле или директории (размер, владелец, права доступа и так далее).

Конечно, PHP представляет возможность для получения такой информации с помощью функций,например filesize() и fileowner(). Но PHP5 основан на использовании концепции ООП. Поэтому лучше использовать современные методы работы с языком программирования. На нашем сайте есть уроки, посвященные работе с итераторами.

Как уже сообщалось во водной части урока, мы рассмотрим использование FilesystemIterator, RecursiveDirectoryIterator и GlobIterator. Первый наследуется от DirectoryIterator, а остальные от FilesystemIterator. Они все имеют один и тот же конструктор, который принимает два параметра:

$path (обязательный): путь к пункту файловой системы, над которым совершаются операции
$flags (опциональный): один или несколько флагов, перечисленных в документации

Реальное различие в данных итераторах заключается в их использовании для навигации по заданному пути.


FilesystemIterator

Использовать FilesystemIterator очень просто. Рассмотрим в действии. Представляем два примера. Первый показывает поиск всех файлов и каталогов, имена которых начинаются на “te”. Второй пример использует другой итератор RegexIterator для поиска всех файлов и каталогов, имена которых заканчиваются на “t.dat” или “t.php”. Итератор RegexIterator используется для фильтрации результата на основе регулярных выражений.
1 <?php
2 $iterator = new FilesystemIterator(".");
3 $filelist = array();
4 foreach($iterator as $entry) {
5 if (strpos($entry->getFilename(), "te") === 0) {
6 $filelist[] = $entry->getFilename();
7 }
8 }

Выше приведенный код выдаст результат, аналогичный предыдущим примерам.

Второй пример с применением RegexIterator:
1 <?php
2 $iterator = new FilesystemIterator(".");
3 $filter = new RegexIterator($iterator, '/t.(php dat)$/');
4 $filelist = array();
5 foreach($filter as $entry) {
6 $filelist[] = $entry->getFilename();
7 }

Он будет выводить:
1 array (
2 0 => 'script.php',
3 1 => 'test.dat'
4 )


RecursiveDirectoryIterator

Итератор RecursiveDirectoryIterator обеспечивает интерфейс для рекурсивного прохода по директориям файловой системы. Он имеет несколько полезных методов, таких как getChildren() и hasChildren(), которые возвращают итератор для текущего места, если это директория, и проверяют, является ли текущая точка входа директорией. Следующий пример демонстрирует использование RecursiveDirectoryIterator и getChildren(). Результат будет такой же, как и в предыдущих примерах.
1 <?php
2 $iterator = new RecursiveDirectoryIterator('.');
3 $filter = new RegexIterator($iterator->getChildren(), '/t.(php dat)$/');
4 $filelist = array();
5 foreach($filter as $entry) {
6 $filelist[] = $entry->getFilename();
7 }


GlobIterator

Итератор GlobIterator выполняет проход по файловой системе также, как и функция glob(). Первый параметр может включать шаблон для имени. Пример демонстрирует использование GlobIterator с тем же результатом, что и ранее.
1 <?php
2 $iterator = new GlobIterator("te*");
3 $filelist = array();
4 foreach($iterator as $entry) {
5 $filelist[] = $entry->getFilename();
6 }


Заключение

В данном уроке демонстрируется использование различных подходов для достижение одинаковой цели: получение списка файлов и директорий. Следует запомнить следующие ключевые моменты:

Функция glob() является встроенным решением, но она недостаточно гибкая.
Решение на основе opendir(), readdir(), и closedir() более сложное и требует дополнительной фильтрации, но оно более гибкое.
Функция scandir() требует дополнительной фильтрации, но работает без обработки дескриптора.
Если вы используете подход ООП, то следует применять библиотеку SPL. Дополнительно вы можете расширить классы своим функционалом.
Итератор GlobIterator имеет функцию предварительной фильтрации, а другие используют RegexIterator.

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: phpmaster.com/list-files-and-directories-with-php/
Перевел: Сергей Фастунов