專案中常需掃描目錄結構(如插件載入、模板列表、檔案管理器)。本文提供一個可復用的 DirScanner 類,支援「僅目錄」「僅檔案」「目錄+檔案樹」三種模式,並附帶完整使用範例。
<?php
class DirScanner {
private $dirList = [];
private $fileList = [];
private $treeList = [];
/**
* 獲取目錄列表(不遞迴)
* @param string $dir 絕對或相對路徑
* @return array 目錄名陣列
*/
public function getDirs(string $dir): array {
$this->dirList = [];
if (!is_dir($dir)) {
$this->dirList[] = "[Path] '$dir' not found or not a directory";
return $this->dirList;
}
$handle = opendir($dir);
if ($handle) {
while (($entry = readdir($handle)) !== false) {
if ($entry !== '.' && $entry !== '..' && !str_contains($entry, '.')) {
$this->dirList[] = $entry;
}
}
closedir($handle);
}
return $this->dirList;
}
/**
* 獲取檔案列表(不遞迴)
* @param string $dir
* @return array 檔案名陣列
*/
public function getFiles(string $dir): array {
$this->fileList = [];
if (!is_dir($dir)) {
$this->fileList[] = "[Path] '$dir' not found or not a directory";
return $this->fileList;
}
$handle = opendir($dir);
if ($handle) {
while (($entry = readdir($handle)) !== false) {
if ($entry !== '.' && $entry !== '..' && str_contains($entry, '.')) {
$this->fileList[] = $entry;
}
}
closedir($handle);
}
return $this->fileList;
}
/**
* 獲取目錄樹(遞迴:目錄下的檔案)
* @param string $dir
* @return array ['DirList' => [...], 'FileList' => [dir => [...]]]
*/
public function getTree(string $dir): array {
$this->treeList = ['DirList' => [], 'FileList' => []];
if (!is_dir($dir)) {
$this->treeList[] = "[Path] '$dir' not found or not a directory";
return $this->treeList;
}
$dirs = $this->getDirs($dir);
$this->treeList['DirList'] = $dirs;
foreach ($dirs as $subDir) {
$fullPath = $dir . DIRECTORY_SEPARATOR . $subDir;
$this->treeList['FileList'][$subDir] = $this->getFiles($fullPath);
}
return $this->treeList;
}
}
<?php
require_once 'DirScanner.php';
$scanner = new DirScanner();
$base = __DIR__ . '/example'; // 測試目錄
// 1. 僅獲取一級目錄
$dirs = $scanner->getDirs($base);
print_r($dirs);
/*
Array
(
[0] => example_one
[1] => example_two
)
*/
// 2. 僅獲取指定目錄下的檔案
$files1 = $scanner->getFiles($base . '/example_one');
$files2 = $scanner->getFiles('E:/Workspace/example_two'); // 絕對路徑同樣支援
print_r($files1);
/*
Array
(
[0] => example.sql
[1] => example.txt
)
*/
// 3. 獲取目錄樹(目錄 + 其下檔案)
$tree = $scanner->getTree($base);
print_r($tree);
/*
Array
(
[DirList] => Array
(
[0] => example_one
[1] => example_two
)
[FileList] => Array
(
[example_one] => Array
(
[0] => example.sql
[1] => example.txt
)
[example_two] => Array
(
[0] => example.php
)
)
)
*/
$maxDepth 參數防止過深遞迴導致棧溢出。.php、忽略 .git)。RecursiveDirectoryIterator + RecursiveIteratorIterator,功能更強大:$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $path => $splFileInfo) {
if ($splFileInfo->isDir()) {
echo "[DIR] $path\n";
} else {
echo "[FILE] $path\n";
}
}
DirScanner 類封裝了 opendir/readdir/closedir 底層操作,提供清晰的三種掃描介面,適合快速集成到舊專案或輕量級需求。新專案或複雜掃描需求(如需檔案大小、修改時間、權限、软連結處理)建議直接使用 SPL 迭代器,功能更完備、效能更優、代碼更標準化。