Итерация файлов и каталогов в PHP
сырыхфункций PHP, таких, как итерация файлов и каталогов. По мере развития все более высоких уровней абстракции мы часто перестаём помнить, как работать на низком уровне. В реальности это имеет множество последствий, особенно с точки зрения производительности.
По мере проведения этих оптимизаций я замечаю, что моё приложение поддерживает растущие нагрузки, несмотря на снижение потребления аппаратных ресурсов. Надеюсь, что приведённые ниже фрагменты помогут не только молодым разработчикам, но и опытным профессионалам, которые ищут идеи по оптимизации производительности.
В PHP существует несколько вариантов итерации/перебора файлов и каталогов:
- Функция
glob()
- Класс
RecursiveDirectoryIterator
- Функция
scandir()
- PHP генераторы
Метод 1: Использование glob()
Функция glob
извлекает файлы и каталоги, соответствующие шаблону. Она полезна, когда необходимо задать некое правило для извлечения элементов из структуры файловой системы.
Для получения только каталогов можно также передать второй параметр в качестве константы.
<?php
$directory = 'path/to/directory'; /// Заменить на фактический путь к каталогу
// Извлечение файлов и каталогов, соответствующих шаблону
$items = glob($directory . '/*');
foreach ($items as $item) {
if (is_file($item)) {
echo "File: {$item}\n";
}
if (is_dir($item)) {
echo "Directory: {$item}\n";
}
}
// Итерация по директориям
$directories = glob($directory . '/*', GLOB_ONLYDIR);
foreach ($directories as $dir) {
echo "Directory: $dir\n";
}
Способ 2: Использование класса RecursiveDirectoryIterator
Очевидно, что это более объектно-ориентированный подход.
<?php
$directory = 'path/to/directory'; // Заменить на фактический путь к каталогу
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $item) {
$path = $item->getPathname();
if ($item->isFile()) {
echo "File: {$path}\n";
} elseif ($item->isDir()) {
echo "Directory: {$path}\n";
}
}
Метод 3: Использование scandir()
Функция scandir()
— это ещё одна возможность итерации файлов и каталогов в PHP. Она возвращает массив имён файлов и каталогов, включая текущий каталог (.
) и родительский каталог (..
).
<?php
$directory = 'path/to/directory'; // Заменить на фактический путь к каталогу
$entries = scandir($directory);
foreach ($entries as $entry) {
if ($entry !== '.' && $entry !== '..') {
$path = $directory . '/' . $entry;
if (is_file($path)) {
echo "File: {$path}\n";
} elseif (is_dir($path)) {
echo "Directory: {$path}\n";
}
}
}
В данном примере цикл foreach
перебирает все записи, исключая текущий каталог (.
) и родительский каталог (..
). Переменная $path
строится путём конкатенации пути ($directory
) и имени файла или каталога ($entry
).
Метод 4: Использование генераторов
Генераторы в PHP могут использоваться для итерационного перебора файлов и каталогов. Генераторы обеспечивают эффективный способ генерации последовательности значений на лету
, что удобно при работе с большими наборами файлов или каталогов. Узнать больше о генераторах на практических примерах можно в статье: PHP генераторы — практический пример
Приведём пример, демонстрирующий использование генератора для итерации файлов в каталоге:
<?php
// Функция, возвращающая yield
function iterateFiles($directory) {
$files = scandir($directory);
foreach ($files as $file) {
if ($file !== '.' && $file !== '..') {
$path = $directory . '/' . $file;
if (is_file($path)) {
yield $path;
}
}
}
}
$directory = 'path/to/directory'; // Заменить на фактический путь к каталогу
$fileGenerator = iterateFiles($directory);
foreach ($fileGenerator as $file) {
echo "File: $file\n";
}
Напомним, что любая функция, возвращающая yield
, является генератором. Как объясняется в официальной документации:
Когда вызывается генератор, он возвращает объект, который можно итерировать. Когда вы итерируете этот объект (например, в цикле
foreach
), PHP вызывает методы итерации объекта каждый раз, когда вам нужно новое значение, после чего сохраняет состояние генератора и при следующем вызове возвращает следующее значение.
Сохранение и возобновление состояния генератора позволяет сверхэффективно использовать системную память.