文件系統操作是 PHP 後端開發常見需求。本文通過一個完整的「目錄瀏覽器」示例,講解遞歸遍歷目錄的核心函數、邏輯結構與安全注意點。
| 函數 | 用途 |
|---|---|
opendir() | 打開目錄句柄 |
readdir() | 讀取目錄條目 |
is_dir() | 判斷是否為目錄 |
chdir() | 切換工作目錄 |
getcwd() | 獲取當前工作目錄 |
base64_encode() | 路徑編碼傳遞(URL 安全) |
<?php
// 6.php - 目錄瀏覽入口
if (isset($_GET['id'])) {
$path = base64_decode(str_replace(' ', '+', $_GET['id']));
if (is_dir($path)) {
chdir($path);
}
}
$handle = opendir('.');
echo "<h3>當前目錄: " . htmlspecialchars(getcwd()) . "</h3>";
echo "<ul>";
while (false !== ($entry = readdir($handle))) {
if ($entry === '.' ) continue; // 跳過當前目錄
$fullPath = getcwd() . DIRECTORY_SEPARATOR . $entry;
$encodedPath = base64_encode($fullPath);
if (is_dir($fullPath)) {
if ($entry === '..') {
echo "<li><a href='6.php?id={$encodedPath}'>📁 上一級</a></li>";
} else {
echo "<li><a href='6.php?id={$encodedPath}'>📁 {$entry}</a></li>";
}
} else {
echo "<li>📄 {$entry} <small>(" . filesize($fullPath) . " bytes)</small></li>";
}
}
echo "</ul>";
closedir($handle);
?>
function scanDirRecursive($dir, $depth = 0) {
$result = [];
if (!is_dir($dir)) return $result;
$items = scandir($dir);
foreach ($items as $item) {
if ($item === '.' || $item === '..') continue;
$path = $dir . DIRECTORY_SEPARATOR . $item;
$info = [
'name' => $item,
'path' => $path,
'type' => is_dir($path) ? 'dir' : 'file',
'size' => is_file($path) ? filesize($path) : 0,
'mtime' => filemtime($path),
'depth' => $depth
];
if (is_dir($path)) {
$info['children'] = scanDirRecursive($path, $depth + 1);
}
$result[] = $info;
}
return $result;
}
// 使用示例
$tree = scanDirRecursive('/var/www/html');
echo json_encode($tree, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
strpos($realPath, $allowedRoot) === 0scandir() 替代 readdir() 循環,或引入 RecursiveDirectoryIterator (SPL)// PHP 5.3+ SPL 迭代器(更優雅、可控)
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('/path', FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $fileInfo) {
echo str_repeat(' ', $iterator->getDepth()) . $fileInfo->getFilename() . "\n";
}
選擇合適方案:簡單展示用遞歸函數,生產環境推薦 SPL 迭代器配合權限檢查。