Управление папками в среде PHP: функции, итераторы и примеры
Основные подходы к работе с папками в PHP
Наиболее эффективный способ создания и управления папками в PHP - это использование комбинации функций mkdir(), is_dir() и chmod() с обязательной проверкой ошибок. Такой подход гарантирует безопасное взаимодействие с файловой системой и предотвращает неожиданные сбои.
$dir = '/path/to/new/folder';
if (!is_dir($dir)) {
if (mkdir($dir, 0755, true)) {
echo 'Папка создана';
} else {
echo 'Ошибка создания';
}
} else {
echo 'Папка уже существует';
}
В этом примере mkdir() с флагом true рекурсивно создаёт все недостающие родительские директории, а is_dir() предотвращает попытку повторного создания.
Типичные ошибки:
- Недостаточные права доступа - используйте chmod() после создания.
- Игнорирование возвращаемого значения mkdir() - всегда проверяйте результат.
- Передача неверного пути с пробелами или специальными символами - применяйте realpath() или проверку через dirname().
Как проверить существование папки и получить её содержимое?
Для проверки используется is_dir(), для чтения списка файлов - scandir().
$path = './uploads';
if (is_dir($path)) {
$files = scandir($path);
// исключаем '.' и '..'
$files = array_diff($files, array('.', '..'));
foreach ($files as $file) {
echo $file . '\n';
}
} else {
echo 'Директория не найдена';
}
Если папка содержит большое количество элементов, scandir() может потреблять много памяти. В таких случаях используйте итераторы (см. раздел расширенных примеров).
Как удалить пустую папку?
Функция rmdir() удаляет только пустые директории. Для непустых требуется рекурсивное удаление.
$dir = './temp';
if (is_dir($dir)) {
if (rmdir($dir)) {
echo 'Папка удалена';
} else {
echo 'Ошибка удаления (возможно, папка не пуста)';
}
} else {
echo 'Папка не существует';
}
Распространённая ошибка - попытка удалить непустую папку без предварительной очистки. Всегда проверяйте содержимое или используйте рекурсивное удаление.
Как переименовать или переместить папку?
Для этих операций применяется rename(), которая работает как с файлами, так и с директориями.
$old = './old_folder';
$new = './new_folder';
if (is_dir($old)) {
if (rename($old, $new)) {
echo 'Папка переименована/перемещена';
} else {
echo 'Ошибка: возможно, целевая папка уже существует или нет прав';
}
} else {
echo 'Исходная папка не найдена';
}
Если целевая папка уже существует, rename() вернёт false. Перемещение между разными файловыми системами может не поддерживаться.
Как изменить права доступа к папке?
Используется chmod(). Права задаются в восьмеричном формате.
$dir = './secured';
if (is_dir($dir)) {
if (chmod($dir, 0700)) {
echo 'Права изменены на 0700 (только владелец)';
} else {
echo 'Ошибка изменения прав';
}
} else {
echo 'Папка не найдена';
}
Неправильные права (например, 0777) могут создать уязвимость. Также chmod() может не сработать, если PHP работает не от владельца папки.
Расширенные примеры работы с папками в PHP
Ниже приведены более сложные сценарии, демонстрирующие рекурсивные операции, использование SPL-итераторов и обработку ошибок.
Рекурсивное создание папок с проверкой прав
function createFolderRecursive($path, $mode = 0755) {
if (is_dir($path)) {
return true;
}
$parent = dirname($path);
if (!createFolderRecursive($parent, $mode)) {
return false;
}
if (!mkdir($path, $mode)) {
return false;
}
// устанавливаем права для только что созданной папки
chmod($path, $mode);
return true;
}
if (createFolderRecursive('/tmp/a/b/c')) {
echo 'Папка создана рекурсивно';
} else {
echo 'Ошибка';
}
Результат: Папка создана рекурсивно (если права позволяют)
Рекурсивное удаление непустой папки
function deleteFolderRecursive($dir) {
if (!is_dir($dir)) {
return false;
}
$items = scandir($dir);
foreach ($items as $item) {
if ($item == '.' || $item == '..') continue;
$fullPath = $dir . DIRECTORY_SEPARATOR . $item;
if (is_dir($fullPath)) {
deleteFolderRecursive($fullPath);
} else {
unlink($fullPath);
}
}
return rmdir($dir);
}
if (deleteFolderRecursive('./temp_cache')) {
echo 'Папка и её содержимое удалены';
} else {
echo 'Ошибка удаления';
}
Результат: Папка и её содержимое удалены
Обход папки с помощью DirectoryIterator
$path = './documents';
if (is_dir($path)) {
$iterator = new DirectoryIterator($path);
foreach ($iterator as $fileInfo) {
if ($fileInfo->isDot()) continue;
echo $fileInfo->getFilename() . ' - ' . ($fileInfo->isDir() ? 'папка' : 'файл') . ' - ' . $fileInfo->getSize() . ' байт\n';
}
} else {
echo 'Папка не найдена';
}
Пример вывода: readme.txt - файл - 1234 байт images - папка - 4096 байт
Использование RecursiveDirectoryIterator для глубокого обхода
$path = './project';
if (is_dir($path)) {
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS)
);
foreach ($iterator as $fileInfo) {
echo $fileInfo->getPathname() . '\n';
}
} else {
echo 'Папка не найдена';
}
Пример вывода: ./project/src/index.php ./project/src/utils/helper.php ./project/config.json
Копирование папки с содержимым
function copyFolder($source, $dest) {
if (!is_dir($source)) {
return false;
}
if (!is_dir($dest)) {
mkdir($dest, 0755, true);
}
$iterator = new DirectoryIterator($source);
foreach ($iterator as $fileInfo) {
if ($fileInfo->isDot()) continue;
$srcPath = $fileInfo->getPathname();
$destPath = $dest . DIRECTORY_SEPARATOR . $fileInfo->getFilename();
if ($fileInfo->isDir()) {
copyFolder($srcPath, $destPath);
} else {
copy($srcPath, $destPath);
}
}
return true;
}
if (copyFolder('./backup', './archive')) {
echo 'Папка скопирована';
} else {
echo 'Ошибка копирования';
}
Результат: Папка скопирована
Получение размера папки (рекурсивно)
function folderSize($dir) {
$size = 0;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS)
);
foreach ($iterator as $fileInfo) {
$size += $fileInfo->getSize();
}
return $size;
}
echo 'Размер папки: ' . folderSize('./data') . ' байт';
Результат: Размер папки: 245678 байт