許多開發者以為 is_file() 可直接替代 file_exists(),實則不然。二者核心差異在於 **統計信息緩存**,可能導致文件狀態檢測失效。
<?php
$filename = 'test.txt';
// 確保文件存在
file_put_contents($filename, 'test');
// 第一次檢測
if (is_file($filename)) {
echo "$filename exists!\n";
} else {
echo "$filename no exists!\n";
}
// 10 秒內手動刪除文件
sleep(10);
// 第二次檢測
if (is_file($filename)) {
echo "$filename exists!\n";
} else {
echo "$filename no exists!\n";
}
?>
test.txt exists!
test.txt exists! ← 文件已刪除卻仍返回 true
原因: is_file() 內部調用 stat() 系統調用,PHP 會緩存文件統計信息(inode、修改時間、大小等)。同一腳本執行期間,對**同路徑**再次調用 is_file()、filesize()、filemtime() 等函數時,直接讀取緩存,**不再訪問磁盤**。
test.txt exists!
test.txt no exists! ← 正確反映刪除狀態
file_exists() 每次調用都重新訪問文件系統,無緩存機制。
// 在需要實時狀態前調用
clearstatcache(true, $filename); // PHP 5.3+ 支持針對特定路徑清除
if (is_file($filename)) { ... }
| 場景 | 推薦函數 | 理由 |
|---|---|---|
| 高頻只讀檢測(如配置加載) | is_file() / is_dir() | 緩存提升性能 |
| 文件上傳後驗證、刪除後確認、併發環境 | file_exists() 或 clearstatcache() + is_file() | 保證實時性 |
| 僅需判斷存在性(文件/目錄均可) | file_exists() | 語義明確、無緩存 |
| 需區分文件/目錄類型 | is_file() / is_dir() | 類型判斷準確 |
is_file() 緩存機制在**單進程請求**內有效,跨請求不共享clearstatcache() 影響微乎其微spl_file_info 對象複用統計信息記住:**需實時性時用 file_exists() 或手動清緩存**,別讓緩存成了 Bug 溫床。