Создаем папку в PHP если её нет: лучшие практики 2025

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

«Create a folder if it doesn't already exist»: Как не изобретать велосипед в 2025 году

Вы когда-нибудь писали скрипт, который должен сохранять файлы, и вдруг получали ошибку Warning: mkdir(): No such file or directory? Если да — вы не одиноки. Вопрос «Create a folder if it doesn't already exist» на Stack Overflow собрал тысячи просмотров, и не зря. Казалось бы, что может быть проще? Но на практике новички (и не только) часто спотыкаются о подводные камни: права доступа, рекурсивное создание, гонки условий.

В этой статье мы разберём лучшие практики PHP для создания папок на 2025 год. Вы узнаете, как правильно использовать mkdir(), избегать типичных ошибок и писать надёжный код, который не упадёт в самый неподходящий момент. Поехали!

Почему вопрос «Create a folder if it doesn't exist» так популярен?

Каждый второй веб-проект так или иначе работает с файлами: загрузка аватарок, генерация отчётов, кэширование, логи. И везде нужно убедиться, что целевая директория существует. Если её нет — скрипт выдаст ошибку, пользователь увидит «500 Internal Server Error», а вы будете искать баг в три часа ночи.

Проблема в том, что PHP-функция mkdir() не создаёт папку автоматически, если родительская директория отсутствует. Многие разработчики пишут что-то вроде:

if (!file_exists($path)) {
    mkdir($path);
}

И это работает… пока не случится race condition (состояние гонки). Если два скрипта одновременно проверят существование папки и оба попытаются её создать — один из них упадёт с ошибкой. В 2025 году, когда нагрузка на сайты растёт, такие баги становятся критичными.

Функция mkdir() в PHP: разбор полётов

Давайте вспомним сигнатуру:

mkdir(string $directory, int $permissions = 0777, bool $recursive = false, resource $context = ?): bool
  • $directory — путь к создаваемой папке.
  • $permissions — права доступа (по умолчанию 0777, но применяется маска umask).
  • $recursive — если true, создаёт все недостающие родительские директории.
  • $context — потоковый контекст (используется редко).

Главный секрет — параметр $recursive. Большинство проблем решаются именно им. Но обо всём по порядку.

Простой способ: is_dir() + mkdir()

Самый очевидный и правильный способ проверить, существует ли папка — использовать is_dir(), а не file_exists(). Почему? Потому что file_exists() вернёт true и для файла с таким именем, что приведёт к ошибке.

$dir = '/path/to/upload';

if (!is_dir($dir)) {
    mkdir($dir, 0755, true);
}

Здесь мы:

  • Проверяем, что директория не существует и не является файлом.
  • Создаём папку с правами 0755 (владелец может всё, остальные — читать и выполнять).
  • Используем true для рекурсивного создания — если родительской папки /path/to нет, она тоже будет создана.

Этот метод покрывает 90% случаев. Но что если два запроса одновременно выполнят этот код?

Защита от race condition (гонки условий)

В высоконагруженных системах папку могут попытаться создать два скрипта одновременно. Чтобы избежать ошибки, используйте @ (подавление ошибок) или, что лучше, проверяйте результат mkdir():

$dir = '/path/to/cache';

if (!is_dir($dir)) {
    // Пытаемся создать. Если папку уже создал другой процесс — не страшно
    if (!mkdir($dir, 0755, true) && !is_dir($dir)) {
        throw new \RuntimeException('Не удалось создать директорию: ' . $dir);
    }
}

Здесь мы:

  • Проверяем существование.
  • Пытаемся создать.
  • Если mkdir() вернул false, но папка уже существует (создана конкурентом) — всё в порядке.
  • Если же mkdir() не удался и папки нет — бросаем исключение.

Это — золотой стандарт создания папок в PHP в 2025 году.

Права доступа: 0777 vs 0755 vs что-то ещё

Многие копируют mkdir($dir, 0777) из примеров, не задумываясь. Но 0777 — это полный доступ для всех, что опасно. Если злоумышленник загрузит PHP-скрипт в эту папку, он сможет его выполнить.

Рекомендации по правам:

  • 0755 — для директорий, куда загружаются файлы (владелец — всё, группа и остальные — чтение/выполнение).
  • 0700 — для временных или кэш-папок, доступных только владельцу.
  • 0777 — только если вы точно знаете, что делаете (например, для папок uploads на локальном сервере).

Не забывайте про umask. Даже если вы укажете 0777, реальные права будут 0777 & ~umask. Обычно umask равен 0022, поэтому 0777 превращается в 0755. Чтобы быть уверенным, можно временно сменить umask:

$old = umask(0);
mkdir($dir, 0755, true);
umask($old);

Но это уже экзотика. В большинстве случаев достаточно просто указать 0755.

Рекурсивное создание: магия $recursive = true

Представьте, что вам нужно создать папку /var/www/project/storage/logs/2025/04/. Если какой-то из уровней отсутствует, mkdir() без $recursive выдаст ошибку.

Решение — третий параметр:

mkdir('/var/www/project/storage/logs/2025/04/', 0755, true);

PHP сам создаст все недостающие директории. Это удобно и безопасно. Единственный нюанс: если /var/www/project/storage/logs/2025/04/ уже существует, функция вернёт false, но ошибки не будет (если не включён строгий режим). Поэтому всегда провер

Блоги

Рекомендаций по книгам