is_writable() 用於判斷文件或目錄是否可寫,但其結果會被緩存,且受運行用戶權限影響。本文詳細講解函數行為、常見坑點,並提供一個不依賴緩存的自定義替代實現。
bool is_writable(string $filename)
true:文件/目錄存在且當前進程用戶有寫權限false:不存在、不可寫、或權限不足clearstatcache() 可清除www-data、nobody)運行,非 CLI 用戶<?php
$filename = "test.txt";
if (is_writable($filename)) {
echo "可寫";
} else {
echo "不可寫"; // 可能因緩存導致誤判
}
// 正確做法:
clearstatcache();
if (is_writable($filename)) { ... }
/**
* 判斷文件/目錄是否可寫(不依賴 stat 緩存)
* @param string $path
* @return bool
*/
function isWritable($path) {
// 目錄:嘗試創建臨時文件
if (preg_match('/\/$/', $path)) {
$tmp = $path . uniqid(mt_rand()) . '.tmp';
return isWritable($tmp); // 遞歸調用文件邏輯
}
if (file_exists($path)) {
// 文件存在:嘗試以 r+ 模式打開(讀寫不截斷)
$fp = @fopen($path, 'r+');
if ($fp) { fclose($fp); return true; }
return false;
} else {
// 文件不存在:嘗試創建
$fp = @fopen($path, 'w');
if ($fp) {
fclose($fp);
@unlink($path); // 清理測試文件
return true;
}
return false;
}
}
| 場景 | 推薦方式 |
|---|---|
| 高頻調用、性能敏感 | is_writable() + clearstatcache() |
| 權限變更後立即檢查 | 自定義 isWritable()(無緩存) |
| 目錄寫入權限檢查 | 自定義版更可靠(實際嘗試創建) |
| 跨平台(Windows/Unix) | 內置函數行為一致,首選 |
clearstatcache(true, $path)(PHP 5.3+ 支持指定路徑清除)www-data 對存儲目錄有 rwxis_dir() + is_writable() 組合判斷目錄可寫理解 is_writable 的緩存特性與用戶上下文,結合自定義實現靈活應對,能避免大量「明明有權限卻判斷失敗」的坑。