項目文檔、代碼結構展示、部署清單等場景常需生成目錄樹。本文實現一個可復用的 DirTree 類,支持自定義縮進、前綴、換行符,可直接輸出 HTML 或下載文本文件。
<?php
class DirTree {
private $tree = '';
private $options = [
'padding' => '│ ', // 縮進字符
'dirpre' => '├── ', // 目錄前綴
'filepre' => '├── ', // 文件前綴
'newline' => "\n", // 換行符
'showHide' => false, // 是否顯示隱藏文件
];
public function __construct(array $options = []) {
$this->options = array_merge($this->options, $options);
}
/**
* 遞歸生成目錄樹
* @param string $path 起始路徑
* @param int $level 當前層級(內部使用)
* @return $this 鏈式調用
*/
public function createTree($path, $level = 0) {
$level = (int)$level;
$baseName = $this->_basename($path);
// 根節點
if ($level === 0) {
$this->tree .= $baseName . $this->options['newline'];
} else {
$this->tree .= str_repeat($this->options['padding'], $level - 1)
. $this->options['dirpre']
. $baseName
. $this->options['newline'];
}
$nextLevel = $level + 1;
$dirHandle = @opendir($path);
if (!$dirHandle) return $this;
$files = [];
while (($entry = readdir($dirHandle)) !== false) {
if ($entry === '.' || $entry === '..') continue;
if (!$this->options['showHide'] && $entry[0] === '.') continue;
$fullPath = $path . DIRECTORY_SEPARATOR . $entry;
if (is_dir($fullPath)) {
$this->createTree($fullPath, $nextLevel);
} elseif (is_file($fullPath)) {
$files[] = $fullPath;
}
}
closedir($dirHandle);
// 輸出文件
foreach ($files as $file) {
$this->tree .= str_repeat($this->options['padding'], $nextLevel - 1)
. $this->options['filepre']
. $this->_basename($file)
. $this->options['newline'];
}
return $this;
}
/** 獲取文件/目錄基本名(處理編碼) */
private function _basename($path) {
return basename($path);
}
/** 瀏覽器顯示(HTML pre 標籤) */
public function showTree() {
header('Content-Type: text/html; charset=utf-8');
echo ''
. htmlspecialchars($this->tree)
. '';
return $this;
}
/** 下載文本文件 */
public function downloadTree($filename = 'dirtree') {
header('Content-Type: text/plain; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $filename . '.txt"');
echo $this->tree;
return $this;
}
/** 獲取樹字符串 */
public function getTree() {
return $this->tree;
}
/** 重置 */
public function reset() {
$this->tree = '';
return $this;
}
}
?>
<?php
require_once 'DirTree.php';
$tree = new DirTree([
'padding' => '│ ',
'dirpre' => '├── ',
'filepre' => '├── ',
'newline' => '
',
'showHide' => false,
]);
$tree->createTree('D:/projects/myapp')->showTree();
?>
輸出效果:
myapp ├── app │ ├── controllers │ │ ├── IndexController.php │ │ └── UserController.php │ ├── models │ │ └── User.php │ └── views ├── config │ ├── database.php │ └── app.php ├── public │ ├── index.php │ ├── css │ │ └── style.css │ └── js │ └── app.js └── composer.json
<?php
require_once 'DirTree.php';
$tree = new DirTree([
'padding' => ' ',
'dirpre' => '+-- ',
'filepre' => '+-- ',
'newline' => "\r\n", // Windows 換行
]);
$tree->createTree('/var/www/html')->downloadTree('project_structure');
?>
<?php
$tree = new DirTree(['newline' => "\n"]);
$tree->createTree(__DIR__);
$content = $tree->getTree();
// 寫入文件
file_put_contents('structure.txt', $content);
// 或發送郵件、存入數據庫等
?>
| 選項 | 默認值 | 說明 |
|---|---|---|
| padding | '│ ' | 層級縮進字符,建議等寬字體下對齊 |
| dirpre | '├── ' | 目錄行前綴 |
| filepre | '├── ' | 文件行前綴 |
| newline | "\n" | 換行符:\n(Linux)、\r\n(Windows)、<br>(HTML) |
| showHide | false | true 顯示隱藏文件(以 . 開頭) |
php_sapi_name() === 'cli' 自動調整輸出格式exclude 選項支持 glob 模式排除(如 vendor/*、.git/*、*.log)stat())<details><summary> 結構,配合 CSS 實現展開/收起toArray() 返回結構化數組,前端樹組件直用└──、非最後項用 ├──,需預知兄弟節點數量<?php
// 在遍歷前先收集所有條目
$entries = [];
while (($entry = readdir($dirHandle)) !== false) {
// ... 過濾邏輯
$entries[] = ['name' => $entry, 'path' => $fullPath, 'isDir' => is_dir($fullPath)];
}
closedir($dirHandle);
// 輸出時知道索引
foreach ($entries as $idx => $entry) {
$isLast = ($idx === count($entries) - 1);
$prefix = $isLast ? '└── ' : '├── ';
$nextPadding = $isLast ? ' ' : '│ ';
// 遞歸傳遞 $nextPadding 作為下一層 padding
}
?>
DirTree 類封裝了遞歸遍歷、字符串構建、多格式輸出,通過選項配置適應不同場景。生產環境建議添加權限檢查、異常處理、大目錄性能優化(如生成器模式)。