Создать папку, если она не существует: правильный способ в PHP
Всем привет! Я новичок в PHP и пытаюсь сделать простую CMS на WordPress. Мне нужно, чтобы при загрузке изображений на сервер создавалась директория по дате, например /uploads/2024/03/. Но я постоянно получаю ошибку "failed to open stream: No such file or directory", если папки ещё нет.
Вот мой текущий код:
$path = '/var/www/html/uploads/' . date('Y/m');
$file = $path . '/image.jpg';
// Пытаюсь сохранить файл
file_put_contents($file, $data);
Я уже пробовал использовать mkdir($path) перед записью, но всё равно папка не создаётся. Погуглил — пишут, что нужно проверять существование. Я добавил проверку:
if (!file_exists($path)) {
mkdir($path);
}
Но теперь ошибка "mkdir(): No such file or directory"! Что я делаю не так? Почему mkdir не может создать папку, если её нет? Может, нужно права выставлять? Или я неправильно указываю путь? Подскажите, как правильно создать вложенные папки, если их ещё не существует.
Заранее спасибо! Использую PHP 7.4 на Ubuntu.
<<Правильное создание рекурсивных директорий в PHP
Ваша проблема типична для начинающих разработчиков. Ошибка возникает из-за того, что mkdir() по умолчанию не создаёт вложенные каталоги. Когда вы пытаетесь создать /uploads/2024/03/, PHP пытается создать папку 03 внутри 2024, но этой папки тоже нет — отсюда и ошибка.
Решение — использовать рекурсивный режим с помощью параметра recursive = true:
$path = '/var/www/html/uploads/' . date('Y/m');
if (!is_dir($path)) {
mkdir($path, 0755, true); // третий параметр = true включает рекурсию
}
$file = $path . '/image.jpg';
file_put_contents($file, $data);
Детальное объяснение
- Первый параметр — путь к создаваемой директории.
- Второй параметр (0755) — права доступа. 0755 — стандарт для веб-папок: владелец может всё, остальные — читать и выполнять.
- Третий параметр (true) — рекурсивное создание всех недостающих родительских директорий.
Почему file_exists() не подходит?
file_exists() возвращает true и для файлов, и для директорий. Лучше использовать is_dir() — он проверяет именно существование папки:
if (!is_dir($path)) {
mkdir($path, 0755, true);
}
Полный рабочий пример с обработкой ошибок
$baseDir = '/var/www/html/uploads/';
$datePath = date('Y/m');
$fullPath = $baseDir . $datePath;
// Проверяем и создаём папку
if (!is_dir($fullPath)) {
if (!mkdir($fullPath, 0755, true)) {
die('Не удалось создать директорию: ' . $fullPath);
}
}
// Теперь можно сохранять файл
$file = $fullPath . '/image.jpg';
if (file_put_contents($file, $data) === false) {
die('Ошибка записи файла');
}
echo 'Файл успешно сохранён в ' . $file;
Важные моменты для WordPress
- В WordPress используйте
wp_upload_dir()— он возвращает правильный путь к папке загрузок. - Права 0755 обычно достаточны, но если у вас проблемы — проверьте, что веб-сервер (www-data) имеет права на запись в родительскую директорию.
- Для безопасности никогда не используйте права 0777 — это открывает доступ всем.
Теперь ваш код будет работать корректно: mkdir создаст сразу всю цепочку папок uploads/2024/03/, даже если ни одной из них не существует.
Альтернативный подход: функция с проверкой и рекурсией
Если вы предпочитаете более универсальное решение, можно написать небольшую функцию-обёртку:
function ensureDirectoryExists($path, $permissions = 0755) {
if (is_dir($path)) {
return true;
}
// Создаём родительскую директорию рекурсивно
$parent = dirname($path);
if (!is_dir($parent)) {
ensureDirectoryExists($parent, $permissions);
}
return mkdir($path, $permissions);
}
// Использование:
$path = '/var/www/html/uploads/' . date('Y/m');
if (ensureDirectoryExists($path)) {
file_put_contents($path . '/image.jpg', $data);
} else {
echo 'Ошибка создания директории';
}
Почему этот вариант может быть полезен?
- Вы полностью контролируете процесс создания — можно добавить логирование ошибок.
- Рекурсия работает как встроенная, но даёт больше гибкости (например, можно выставить разные права для разных уровней).
- Функция возвращает
true/false, что удобно для условных конструкций.
Однако для большинства случаев проще использовать mkdir($path, 0755, true) — это стандартное и надёжное решение, которое рекомендуют в документации PHP.
Совет: всегда проверяйте, что базовый путь (/var/www/html/uploads/) существует и доступен для записи веб-серверу, иначе никакая рекурсия не поможет.
Ответов пока нет.
Войдите чтобы оставить ответ