phprecursion

Recursive directory iterator get filepath of file with subfolders


I have a function that recursively iterates over a directory tree. This works fine, I get a array returned with the directories and files.

$dir = 'files';
function dirToArray($dir) { 
   
   $result = array(); 

   $cdir = scandir($dir); 
   foreach ($cdir as $key => $value) {

      if (!in_array($value,array(".",".."))) { 
         if (is_dir($dir . DIRECTORY_SEPARATOR . $value)) { 
            $result[$value] = dirToArray($dir . DIRECTORY_SEPARATOR . $value); 
         } 
         else { 
            $result[] = $value;
         } 
      } 
   } 

   return $result; 
}

I then iterate recursively over the returned array to display a nice menu structure to the user, which also works fine.

function printAll($arr) {

    if(!is_array($arr)) {
        echo '<li><div class="sub_menu_path"></div><a href="'.$arr.'" class="file"><i class="fa fa-fw fa-file-text-o"></i>'.$arr.'</a></li>';
    }
    else {
    
        foreach($arr as $k => $v) {

            if(is_array($v)) {  
                echo '<li><div class="sub_menu_path"></div><a href="'.$k.'" class="multi_menu folder"><i class="fa fa-fw fa-folder-o"></i>'.$k.'</a>';                          

                echo '<ul class="sub_menu">';                               
                    printAll($v);                               
                echo '</ul>';

                echo '</li>';
            }
            else {
                echo '<li><div class="sub_menu_path"></div><a href="'.$v.'" class="file"><i class="fa fa-fw fa-file-text-o"></i>'.$v.'</a></li>';                                   
            }
        }
    }
}               

printall(dirToArray($dir));

result:

enter image description here

but what I want is when I display the file to the user wrapped in an html <a href="$value">$value</a> how to get the complete path including subfolders? for example: files/Products/Cress/Ramnunculus/Introduction/file.txt I only get file.txt so when I click in file.txt it says file not found of course.

EDIT (Solution):

as suggested in the answer, I added a extra parameter. I changed the variable $v to $k because it gives a array to string conversion.

function printAll($arr, $path = '') {
    if(!is_array($arr)) {
        echo '<li><div class="sub_menu_path"></div><a href="'.$arr.'" class="file"><i class="fa fa-fw fa-file-text-o"></i>'.$arr.'</a></li>';
    }
    else {
    
        foreach($arr as $k => $v) {

            $file_path = $path . ($path == '' ? '' : '/') . $k;
            
            if(is_array($v)) {  
                echo '<li><div class="sub_menu_path"></div><a href="" class="multi_menu folder"><i class="fa fa-fw fa-folder-o"></i>'.$k.'</a>';

                echo '<ul class="sub_menu">';                               
                    printAll($v, $file_path);                               
                echo '</ul>';

                echo '</li>';
            }
            else {
                echo '<li><div class="sub_menu_path"></div><a href="'.$file_path.'" class="file"><i class="fa fa-fw fa-file-text-o"></i>'.$v.'</a></li>';                                   
            }
        }
    }
}               
    
printall(dirToArray($dir));

Solution

  • Include optional parameter $path = ''

        function printAll($arr, $path = '') {
    
            if(!is_array($arr)) {
                $file_path = $path . ($path == '' ? '' : '/') . $arr;
                echo '<li><div class="sub_menu_path"></div><a href="'.$file_path.'" class="file"><i class="fa fa-fw fa-file-text-o"></i>'.$arr.'</a></li>';
            }
            else {
    
                foreach($arr as $k => $v) {
                    if(is_array($v)) {
                        $file_path = $path . ($path == '' ? '' : '/') . $k;
    
                        echo '<li><div class="sub_menu_path"></div><a href="'.$file_path.'" class="multi_menu folder"><i class="fa fa-fw fa-folder-o"></i>'.$k.'</a>';
    
                        echo '<ul class="sub_menu">';
                        printAll($v, $file_path);
                        echo '</ul>';
    
                        echo '</li>';
                    }
                    else {
                        $file_path = $path . ($path == '' ? '' : '/') . $v;
                        echo '<li><div class="sub_menu_path"></div><a href="'.$file_path.'" class="file"><i class="fa fa-fw fa-file-text-o"></i>'.$v.'</a></li>';
                    }
                }
            }
        }