Как удалять файлы в PHP: основные приёмы и советы
Удаление файла с помощью PHP
Как удалить один файл самым простым и эффективным способом?
Для удаления файла в PHP используется встроенная функция unlink(). Она принимает путь к файлу и возвращает true в случае успеха или false при ошибке. Пример:
$file = 'example.txt';
if (unlink($file)) {
echo 'Файл удалён';
} else {
echo 'Ошибка удаления';
}
Функция не генерирует исключения, а только возвращает логическое значение. Для детальной обработки ошибок следует использовать проверку прав доступа и существования файла перед вызовом.
Частая ошибка: файл не существует или нет прав на его удаление. Решение - предварительная проверка is_file() и is_writable().
Как удалить файл только после проверки его существования?
Вызов unlink для несуществующего файла вызывает предупреждение. Чтобы избежать этого, используется комбинация с file_exists() или is_file():
$path = 'temp/data.txt';
if (is_file($path)) {
unlink($path);
echo 'Файл удалён';
} else {
echo 'Файл не найден';
}
Цель - исключить ложные срабатывания и предупреждения в логах.
Как обработать ошибку удаления с помощью исключений?
Если необходимо получить исключение вместо логического результата, можно создать обёртку:
function deleteFile(string $path): void {
if (!is_file($path)) {
throw new InvalidArgumentException('Файл не найден');
}
if (!unlink($path)) {
throw new RuntimeException('Не удалось удалить файл');
}
}
try {
deleteFile('secret.txt');
} catch (Throwable $e) {
echo 'Ошибка: ' . $e->getMessage();
}
Такой подход удобен в объектно-ориентированном коде, где требуется строгая обработка ошибок.
Ошибка: файл может быть занят другим процессом (например, открыт в текстовом редакторе). Решение - использовать fclose() перед удалением, если файл открыт в текущем скрипте.
Как удалить несколько файлов по маске?
Для удаления всех файлов определённого расширения или шаблона используется glob() в сочетании с циклом:
$files = glob('backup/*.tmp');
foreach ($files as $file) {
if (is_file($file)) {
unlink($file);
}
}
Цель - массовая очистка временных файлов или кэша.
Проблема: при большом количестве файлов цикл может выполняться долго. Решение - использовать array_map() или отключать таймаут скрипта.
Как удалить файл с использованием командной строки?
Если необходимо выполнить удаление средствами ОС (например, для обхода ограничений PHP), применяется exec() или shell_exec():
$path = '/tmp/old.log';
shell_exec('rm -f ' . escapeshellarg($path));
Этот метод требует включения exec в php.ini и повышенных мер безопасности (экранирование аргументов).
Цель - удаление файлов с особыми правами или атрибутами, не доступными PHP.
Ошибка: неэкранированный путь приводит к уязвимости инъекции команд. Решение - всегда использовать escapeshellarg().
Как удалить файл после его загрузки (автоматическая очистка)?
После обработки загруженного файла часто требуется удалить оригинал или временную копию. Пример:
$uploadDir = 'uploads/';
$tmpFile = $uploadDir . basename($_FILES['file']['tmp_name']);
// ... обработка файла ...
unlink($tmpFile);
Цель - экономия дискового пространства и соблюдение политики безопасности (не хранить конфиденциальные данные дольше необходимого).
Какие типичные ошибки возникают при удалении файлов?
- Файл не существует - проверять через is_file().
- Недостаточно прав - проверять через is_writable().
- Файл заблокирован - закрыть все дескрипторы fclose().
- Путь содержит неверные символы - использовать realpath().
- Рекурсивное удаление вместо файла - для директорий нужна rmdir() или итератор.
Все эти ситуации обрабатываются с помощью предусловий и блоков try-catch.
Расширенные примеры удаления файлов в PHP
Пример 1. Удаление файла с детальным логированием и проверками.
function safeUnlink(string $path): bool {
if (!is_file($path)) {
error_log('Файл не найден: ' . $path);
return false;
}
if (!is_writable($path)) {
error_log('Нет прав на удаление: ' . $path);
return false;
}
$result = unlink($path);
if ($result) {
error_log('Файл удалён: ' . $path);
} else {
error_log('Ошибка unlink: ' . $path);
}
return $result;
}
safeUnlink('/tmp/test.log');
Результат: запись в error_log (или syslog).
Пример 2. Удаление всех файлов старше 7 дней в директории.
$directory = 'cache/';
$iterator = new DirectoryIterator($directory);
$now = time();
$maxAge = 7 * 24 * 3600;
foreach ($iterator as $fileinfo) {
if ($fileinfo->isFile() && ($fileinfo->getMTime() + $maxAge < $now)) {
unlink($fileinfo->getPathname());
echo 'Удалён старый файл: ' . $fileinfo->getFilename() . PHP_EOL;
}
}
Удалён старый файл: temp_1.dat Удалён старый файл: temp_2.dat
Пример 3. Удаление файла с использованием CURL (если доступ к файлу по HTTP).
$url = 'https://example.com/remote/delete.php?file=test.txt';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Ответ сервера: 'File deleted' или сообщение об ошибке.
Пример 4. Удаление файла с помощью SPL FileObject.
$file = new SplFileObject('/tmp/delete_me.txt');
if ($file->isFile()) {
unlink($file->getPathname());
echo 'Удаление через SPL выполнено';
}
Удаление через SPL выполнено
Пример 5. Обработка ошибок при удалении с контекстом и подробным сообщением.
$path = '/etc/passwd'; // нет прав
set_error_handler(function($severity, $message, $file, $line) {
throw new ErrorException($message, 0, $severity, $file, $line);
});
try {
unlink($path);
} catch (ErrorException $e) {
echo 'Ошибка удаления: ' . $e->getMessage();
} finally {
restore_error_handler();
}
Ошибка удаления: unlink(/etc/passwd): Permission denied
Пример 6. Удаление символической ссылки (unlink удаляет саму ссылку, а не цель).
symlink('/tmp/real_file', '/tmp/link');
unlink('/tmp/link');
if (!is_link('/tmp/link')) echo 'Символическая ссылка удалена';
Символическая ссылка удалена