<?php
/**
* 遞歸創建多級目錄
* @param string $path 目標路徑(相對或絕對)
* @param int $mode 權限,默認 0755
* @return bool 成功返回 true
*/
function ensure_dir(string $path, int $mode = 0755): bool {
// PHP 5.0+ 內建遞歸參數,無需手寫遞歸
return is_dir($path) || mkdir($path, $mode, true);
}
// 使用示例
ensure_dir('2007/3/4'); // 當前目錄下創建 2007/3/4
ensure_dir('/var/www/uploads/2024/05/15', 0775); // 絕對路徑
mkdir($path, $mode, true) 第三個參數 $recursive = true 會自動創建父目錄,底層實現已處理併發競爭、權限繼承等邊界情況,強烈建議直接使用內建函數,勿重複造輪子。
function createFolder_recursive(string $path, int $mode = 0755): bool {
if (is_dir($path)) return true;
$parent = dirname($path);
if ($parent !== '.' && $parent !== '/' && !createFolder_recursive($parent, $mode)) {
return false;
}
return @mkdir($path, $mode);
}
高併發場景下,多進程同時調用 mkdir(..., true) 可能觸發 File exists 警告。解決方案:
function ensure_dir_atomic(string $path, int $mode = 0755): bool {
if (is_dir($path)) return true;
// 嘗試創建,忽略 EEXIST 錯誤
$result = @mkdir($path, $mode, true);
if ($result) return true;
$error = error_get_last();
// 併發導致目錄已存在,視為成功
return $error && str_contains($error['message'], 'File exists') && is_dir($path);
}
0755(擁有者寫、組讀執行、其他讀執行)0775 + 設置 setgid:chmod g+s uploads/,新文件自動繼承組0700,僅擁有者可訪問0777,除非臨時測試| 現象 | 原因 | 解決 |
|---|---|---|
| Permission denied | 父目錄無寫權限、或 Web 用戶非目錄擁有者 | chown www:www /path;chmod 755 父目錄 |
| No such file or directory | 路徑中含特殊字符、或相對路徑基準錯誤 | 使用絕對路徑 __DIR__ . '/../data' |
| File exists 警告 | 併發創建同一目錄 | 用 @ 抑制警告、或檢查 is_dir 後再創建 |
| Windows 路徑分隔符 | 代碼寫死 / 或 \ | 用 DIRECTORY_SEPARATOR 或統一 /(PHP Windows 也支援) |