$dir = $_SERVER['DOCUMENT_ROOT'] . '/inc/';
$d = opendir($dir);
while (false !== ($f = readdir($d))) {
if (is_file($f)) { // ❌ 錯誤:$f 只是文件名,相對當前工作目錄
echo "<h2>$f</h2>";
} else {
echo "<h2>是目錄 $f</h2>";
}
}
closedir($d);
輸出:只有 footer.html 被識別為文件,其餘全成「目錄」。
readdir() 返回**不帶路徑的文件名**(如 header.html)is_file() / is_dir() 默認相對**當前工作目錄**(getcwd()),而非 $dirfooter.html),才會「巧合」判斷正確while (false !== ($f = readdir($d))) {
$fullPath = $dir . $f; // 或 "$dir/$f"
if (is_file($fullPath)) {
echo "<h2>$f</h2>";
} else {
echo "<h2>是目錄 $f</h2>";
}
}
$iterator = new FilesystemIterator($dir, FilesystemIterator::SKIP_DOTS);
foreach ($iterator as $fileInfo) {
echo $fileInfo->isFile() ? "<h2>{$fileInfo->getFilename()}</h2>"
: "<h2>是目錄 {$fileInfo->getFilename()}</h2>";
}
優勢:
✅ 自動過濾 . ..
✅ 內建 isFile() isDir() getSize() getMTime() 等方法
✅ 物件導向,可鏈式調用 RegexIterator 過濾擴展名
readdir/scandir/glob 返回值是否拼接了目錄路徑?. ..?is_link() 判斷?FilesystemIterator 避免一次性載入陣列?strtolower() 統一比對?is_file($filename) 的 $filename **必須是相對執行腳本的完整路徑**,而非僅文件名。這是 PHP 文件系統函數「相對工作目錄」設計導致的最經典坑。養成 $full = $dir . $name 肌肉記憶,或直接升級 SPL 迭代器,一勞永逸。