W3docs

PHP Directory

PHP Directory: полное справочное руководство для PHP-разработчиков.

PHP поставляется с набором встроенных функций для работы с директориями, которые позволяют скриптам проверять, создавать, читать и удалять папки в файловой системе сервера — без обращения к операционной системе напрямую. На этой странице описано, что делает каждая основная функция, когда её применять и каких распространённых ошибок следует избегать.

Это дополнение к PHP File Handling и более широкому справочнику PHP Filesystem: файлы находятся внутри директорий, поэтому обе темы почти всегда используются вместе.

Зачем нужны операции с директориями

Практически каждое нетривиальное приложение обращается к файловой системе. Функции для работы с директориями необходимы для:

  • Организации загруженных файлов — сортировки загрузок пользователей по папкам на основе пользователя или даты (см. PHP File Upload).
  • Создания структуры проекта на лету — генерации папок кэша, логов или экспорта при первом обращении к ним.
  • Перебора содержимого — получения списка всех шаблонов, изображений или файлов данных в папке для пакетной обработки.
  • Очистки — удаления временных директорий после завершения задачи.

Поскольку эти функции входят в ядро PHP, они одинаково работают на Linux, macOS и Windows (везде принимается / в качестве разделителя), что делает их более переносимыми по сравнению с вызовом mkdir или ls через exec().

Основные функции для работы с директориями

ФункцияНазначение
mkdir($path, $mode, $recursive)Создать директорию. Передайте true для $recursive, чтобы создать все отсутствующие родительские папки.
rmdir($path)Удалить директорию — она должна быть пустой.
is_dir($path)Вернуть true, если путь существует и является директорией.
scandir($path)Вернуть массив всех элементов директории (включая . и ..).
opendir() / readdir() / closedir()Открыть дескриптор директории и читать элементы по одному.
getcwd()Вернуть текущую рабочую директорию.
chdir($path)Изменить текущую рабочую директорию.

scandir() vs. opendir()

Обе функции выводят содержимое директории, но подходят для разных задач:

  • scandir() загружает все элементы в массив сразу. Код получается лаконичным и легко сортируется, но расходует память пропорционально числу файлов. Лучше всего подходит для папок малого и среднего размера.
  • opendir() / readdir() передают элементы по одному. Это обеспечивает постоянный расход памяти даже для директорий с десятками тысяч файлов. Лучше всего подходит для очень больших папок.

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

Пример: создание директории и вывод её содержимого

Этот скрипт проверяет, существует ли директория, создаёт её (вместе с отсутствующими родительскими папками) если нет, а затем выводит её содержимое:

<?php
$dir = 'uploads/images';

// Create the directory and any missing parents if it doesn't exist
if (!is_dir($dir)) {
    mkdir($dir, 0755, true);
    echo "Directory created: $dir\n";
}

// List directory contents, skipping the . and .. entries
$files = scandir($dir);
echo "Contents of $dir:\n";
foreach ($files as $file) {
    if ($file !== '.' && $file !== '..') {
        echo "- $file\n";
    }
}
?>

Третий аргумент mkdir() (true) — это флаг рекурсивного создания: без него mkdir('uploads/images') завершится ошибкой, если uploads ещё не существует. 0755 — это восьмеричный код разрешений (владелец может читать/писать/выполнять, остальные — читать/выполнять) и игнорируется в Windows.

Пример: потоковое чтение с opendir()

Для больших директорий читайте элементы по одному, не формируя полный массив:

<?php
$dir = __DIR__;

if ($handle = opendir($dir)) {
    while (($entry = readdir($handle)) !== false) {
        if ($entry !== '.' && $entry !== '..') {
            $type = is_dir("$dir/$entry") ? 'dir ' : 'file';
            echo "[$type] $entry\n";
        }
    }
    closedir($handle);
}
?>

Обратите внимание на строгое сравнение !== false: файл с буквальным именем "0" является ложным значением, поэтому нестрогое условие while ($entry = readdir(...)) завершится раньше времени. Всегда сравнивайте явно с false.

Удаление директорий

rmdir() удаляет только пустую директорию. Чтобы удалить директорию с файлами, сначала очистите её содержимое — обычно с помощью рекурсивного вспомогательного метода:

<?php
function removeDir(string $dir): void {
    foreach (scandir($dir) as $entry) {
        if ($entry === '.' || $entry === '..') {
            continue;
        }
        $path = "$dir/$entry";
        is_dir($path) ? removeDir($path) : unlink($path);
    }
    rmdir($dir);
}
?>

Этот код перебирает каждый элемент, рекурсивно обходя поддиректории и удаляя файлы через unlink(), поэтому к моменту вызова rmdir() директория уже пуста.

Распространённые ошибки

  • mkdir() без флага рекурсивного создания завершается ошибкой, если какая-либо родительская папка отсутствует. Передавайте true при создании вложенных путей.
  • Разрешения вычитаются с учётом umask — фактический режим равен $mode & ~umask(), поэтому 0777 может стать 0755.
  • rmdir() на непустой папке возвращает false и выдаёт предупреждение. Сначала очистите её.
  • scandir() включает . и .. — фильтруйте их перед обработкой.
  • Относительные пути зависят от getcwd(), то есть от рабочей директории скрипта, а не от расположения файла. Используйте __DIR__ для привязки путей к текущему файлу.

Работа с директориями: схема

graph TD
A[Check Directory] --> B{Exists?}
B -->|No| C[mkdir]
B -->|Yes| D[scandir / opendir]
C --> E[Create Subdirectories]
D --> F[Read Entries]
F --> G[Process Files]
G --> H[close / rmdir]

Итог

Функции PHP для работы с директориями обеспечивают переносимый встроенный способ управления папками: mkdir() и rmdir() создают и удаляют их, is_dir() проверяет их существование, а scandir() или opendir()/readdir() выводят их содержимое. Используйте scandir() для небольших папок из-за его простоты, а потоковое чтение через opendir() — для больших, чтобы избежать лишних затрат памяти. Комбинируйте эти функции с функциями для работы с файлами PHP и обработкой файлов для создания надёжных функций загрузки, кэширования и экспорта.

Практика

Практика
Какие возможности предоставляет PHP Directory?
Какие возможности предоставляет PHP Directory?
Was this page helpful?