Folders Tree in php

4.4k views Asked by At

I want to list the contents of a folder in php.

But i would like to display only the folder and not the files.

In addition, i would like to display a maximum of one sub-folder!

Could you help me please !

My code :

<?php
function mkmap($dir){
    echo "<ul>";   
    $folder = opendir ($dir);

    while ($file = readdir ($folder)) {   
        if ($file != "." && $file != "..") {           
            $pathfile = $dir.'/'.$file;           
            echo "<li><a href=$pathfile>$file</a></li>";           
            if(filetype($pathfile) == 'dir'){               
                mkmap($pathfile);               
            }           
        }       
    }
    closedir ($folder);    
    echo "</ul>";   
}
?>

<?php mkmap('.'); ?>
2

There are 2 answers

1
LSerni On BEST ANSWER

Pass the maximum recursion level to the function. This way you can decide how many levels deep you want to go, at runtime.

Also, it would be a good idea (I think) to have the "I want the dirs or maybe not" decision done externally and passed as a parameter. This way one function can do both.

And finally it's rarely a good idea having a function output HTML. It's best to return it as a string, so that you're more free to move code around. Ideally, you want to have all your logic separated from your presentation View (and more than that; google 'MVC').

Even better would be to pass a HTML template to the mkmap function and have it use that to create the HTML snippet. This way, if in one place you want a <ul> and in another a <ul id="another-tree" class="fancy">, you needn't use two versions of the same function; but that's probably overkill (you might do it easily with str_replace, or XML functions, though, if you ever need it).

function mkmap($dir, $depth = 1, $only_dirs = True){
    $response = '<ul>';
    $folder = opendir ($dir);

    while ($file = readdir ($folder)) {
        if ($file != '.' && $file != '..') {           
            $pathfile = $dir.'/'.$file;
            if ($only_dirs && !is_dir($pathfile))
                continue;
            $response .= "<li><a href=\"$pathfile\">$file</a></li>";
            if (is_dir($pathfile) && ($depth !== 0))
                $response .= mkmap($file, $depth - 1, $only_dirs);
        }
    }
    closedir ($folder);
    $response .= '</ul>';
    return $response;
}


// Reach depth 5
echo mkmap('Main Dir', 5, True);

// The explicit check for depth to be different from zero means
// that if you start with a depth of -1, it will behave as "infinite depth",
// which might be desirable in some use cases.

Templating

There's many way of templating the function, but maybe the simplest is this (for more elaborate customization, XML is mandatory - managing HTML with string functions has nasty space-time continuum implications):

function mkmap($dir, $depth = 1, $only_dirs = True,
    $template = False) {
    if (False === $template) {
        $template = array('<ul>','<li><a href="{path}">{file}</a></li>','</ul>');
    }
    $response = '';
    $folder = opendir ($dir);

    while ($file = readdir ($folder)) {
        if ($file != '.' && $file != '..') {           
            $pathfile = $dir.'/'.$file;
            if ($only_dirs && !is_dir($pathfile))
                continue;
            $response .= str_replace(array('{path}','{file}'), array($pathfile, $file), $template[1]);
            if (is_dir($pathfile) && ($depth !== 0))
                $response .= mkmap($file, $depth - 1, $only_dirs, $template);
        }
    }
    closedir ($folder);
    return $template[0] . $response . $template[2];
}

The function works like before, but you can pass a further argument to customize it:

echo mkmap('Main Dir', 5, True, array(
    '<ul class="filetree">',
    '<li><a href="{path}"><img src="file.png" /><tt>{file}</tt></a></li>',
    '</ul>'));
3
Charaf JRA On

To check if a file is a folder use is_dir() function.

This recursive solution will list folders and subfolders :

 <?php

function mkmap($dir){
    $ffs = scandir($dir);
    echo '<ul>';
    foreach($ffs as $file){
        if($file != '.' && $file!= '..' ){

            $path=$dir.'/'.$file;
             echo "<li><a href='".$path."'>$file</a></li>";           

            if(is_dir($dir.'/'.$file)) mkmap($dir.'/'.$file);

        }
    }
    echo '</ul>';
}

mkmap('main dir');
?>