I recently had to make something like it, so here is a function that does exactly that. Optionally, you can add classnames to files and folders to style them with CSS.
All folders are displayed 'opened', although with a little JS you can make a function to add some 'open-close' behaviour to the list.
<?php
/**
* function makeDirectoryTree
* iterates recursively through a directory
* and lists it in an unordered list
*
* usage: echo makeDirectoryTree(relative/path/to/directory);
*
* @param string $pathname
* @return string
*/
function makeDirectoryTree($pathname){
$path = realpath($pathname);
if(!is_dir($path)){
return "Path does not exist!";
}
$foldertree = new DOMDocument();
/*
* the rootelement of the tree
*/
$ul[""] = $foldertree->createElement('ul');
$ul[""]->setAttribute('id', 'foldertree_root');
$foldertree->appendChild($ul[""]);
/*
* Files in rootfolder
* if not iterated separately, these files will appear alphabetically between the folders
* instead of on top of the list
*
*/
$iterator = new DirectoryIterator($path);
foreach ($iterator as $fileinfo) {
if ($fileinfo->isFile()) {
/*
* the random id could be useful if you want to manipulate an element with JS
* for instance to 'open' or 'close' the folders
* also, add an optional classname to files and folders, so you can
* do some markup with CSS, for instance:
* .folder {color: #f00; list-style-image: url('path/to/images/folder.png');}
* .file {color: #999; list-style-image: url('path/to/images/file.png');}
*/
$random_id = md5(microtime());
$li_element = $foldertree->createElement('li', $fileinfo->getFilename());
$li_element->setAttribute('id', 'li_' . str_ireplace(' ', '', $random_id));
$li_element->setAttribute('class', 'file'); //optional classname
$ul[""]->appendChild($li_element);
}
}
/*
* iterate through the other folders
*/
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name=>$value){
if($value->isDir()){
$relative_path = str_ireplace($path . DIRECTORY_SEPARATOR, "", $value->getPathname());
$path_array = explode(DIRECTORY_SEPARATOR, $relative_path);
$new_dir = array_pop($path_array);
$directory_up = implode(DIRECTORY_SEPARATOR, $path_array);
$random_id = md5(microtime());
$li[$relative_path] = $foldertree->createElement('li', $new_dir);
$li[$relative_path]->setAttribute('id', 'li_' . str_ireplace(' ', '', $random_id));
$li[$relative_path]->setAttribute('class', 'folder'); //optional classname
$ul[$relative_path] = $foldertree->createElement('ul');
$ul[$relative_path]->setAttribute('id', 'ul_' . str_ireplace(' ', '', $random_id));
$li[$relative_path]->appendChild($ul[$relative_path]);
$ul[$directory_up]->appendChild($li[$relative_path]);
$iterator = new DirectoryIterator($value->getPathname());
foreach ($iterator as $fileinfo) {
if ($fileinfo->isFile()) {
$random_id = md5(microtime());
$li_element = $foldertree->createElement('li', $fileinfo->getFilename());
$li_element->setAttribute('id', 'li_' . str_ireplace(' ', '', $random_id));
$li_element->setAttribute('class', 'file'); //optional classname
$ul[$relative_path]->appendChild($li_element);
}
}
}
}
return $foldertree->saveHTML();
}
?>
I recently had to make something like it, so here is a function that does exactly that. Optionally, you can add classnames to files and folders to style them with CSS. All folders are displayed 'opened', although with a little JS you can make a function to add some 'open-close' behaviour to the list.