unlink($file) or die("無法刪除檔案: $file");
返回 `true` 成功,`false` 失敗(權限不足、檔案不存在、被鎖定等)。
刪除檔案實際是修改**目錄項目**,需對**所在目錄**擁有寫入(`w`)與執行(`x`)權限,而非檔案本身。
例如:`/var/www/uploads/photo.jpg` 屬於 `www-data:www-data` 644,目錄 `/var/www/uploads` 屬於 `root:root` 755。PHP 以 `www-data` 執行,無法在目錄中刪除項目 → 失敗。
function canDeleteFile(string $path): bool {
if (!file_exists($path)) return false;
if (!is_file($path)) return false; // 目錄需用 rmdir
$dir = dirname($path);
// 檢查目錄是否可寫(隱含執行權限)
if (!is_writable($dir)) return false;
// 額外:檢查檔案本身是否可寫(某些系統需檔案 w 權限才能 unlink)
if (!is_writable($path)) return false;
return true;
}
// 使用
if (canDeleteFile($file)) {
unlink($file);
} else {
error_log("刪除失敗:權限不足 $file");
}
function safeDelete(string $filepath): bool {
// 1. 路徑編碼統一(Windows 中文路徑常見問題)
$filepath = iconv('UTF-8', 'GBK//IGNORE', $filepath); // 視伺服器編碼調整
// 2. 存在性
if (!file_exists($filepath)) {
trigger_error("檔案不存在: $filepath", E_USER_WARNING);
return false;
}
// 3. 權限
if (!is_writable(dirname($filepath)) || !is_writable($filepath)) {
trigger_error("權限不足無法刪除: $filepath", E_USER_WARNING);
return false;
}
// 4. 執行刪除
$result = @unlink($filepath);
if (!$result) {
trigger_error("unlink 執行失敗: $filepath", E_USER_ERROR);
}
return $result;
}
function rrmdir(string $dir): bool {
if (!is_dir($dir)) return false;
$items = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($items as $item) {
$item->isDir() ? rmdir($item->getPathname()) : unlink($item->getPathname());
}
return rmdir($dir);
}