Click here to Skip to main content
15,906,329 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
PROBLEM STATEMENT

I have 1000s of files stored in folder structure in the following format

<root_directory>/year/month/day/category/file.ext


Based on certain parameters I need to select one or many top level folder(s) and compress all or selected files from it to one zip file on the go and avail it to the user to downloaded. Now to compress all these files I am using a method shown in solution of this question on StackOverflow Download multiple files as a zip-file using php - Stack Overflow[^] .

this method requires an array having full path of files need to compress and that's where I am stucked at.

SITUATION

It's kinda weird what I am facing right now. I have a function that returns an array of all files in a provided folder and its subfolder. Now the problem is when I am print_r($arr) within the function where $arr has all the data it's showing me data but when I assign that data to a variable calling function and print_r($variable) it's an empty array();

I dig in deeper and observed that $variable has multiple arrays assigned in it may be because it's recursive.

Let me give some example code...

PHP
<?php

$arrGlobal = array(); // global variable

function listFolderFiles($dir) {
	    $ffs = scandir($dir);

	    $arr = array();

	    unset($ffs[array_search('.', $ffs, true)]);
	    unset($ffs[array_search('..', $ffs, true)]);

	    if (count($ffs) < 1)
	        return;

	    foreach($ffs as $ff){
	        if(is_dir($dir.DIRECTORY_SEPARATOR.$ff)) {
	        	listFolderFiles($dir.DIRECTORY_SEPARATOR.$ff);
	        } else {
	        	array_push($arr, $dir.DIRECTORY_SEPARATOR.$ff);
                // array_push($GLOBALS['arrGlobal'], $dir.DIRECTORY_SEPARATOR.$ff);
	        }
	    }

	    print_r($arr); // here it returns me data
        // $count = count($arr) // count the number of elements in the array

	    return $arr;
}

$variable = listFolderFiles("<path of directory>");
print_r($variable); // here it says Array() i.e. an empty array


?>


now I carefully observed the output of print_r($arr); its something like this

PHP
Array ( [0] => <path_to_file> [1] => <path_to_file> [2] => <path_to_file> )
Array ( [0] => <path_to_file> [1] => <path_to_file> )
Array ( [0] => <path_to_file> [1] => <path_to_file> [2] => <path_to_file> )
Array ( [0] => <path_to_file> [1] => <path_to_file> [2] => <path_to_file> [3] => <path_to_file> )


clearly, you can see this variable has 4 arrays in it and it's not repetitive data as each array has different elements and the different number of elements in them. I have also tried with global variable $arrGlobal but the result is same. when I count() length of the array it gave me different lengths as follow

PHP
$count = count($arr)
echo $count;

// OUTPUT
3234


I thought it's an array of array so I tried print_r($arr[0]) and it gave me warning.

<path_to_file><path_to_file><path_to_file><path_to_file>
Notice: Undefined offset: 0 in C:\xampp\htdocs\whoistest\api\index.php on line 314


What I have tried:

I hope I have described everything here. I guess since the function is recursive thus this issue is coming. Please help me resolving this issue asap.
Posted
Updated 2-Jan-18 2:35am
v3

You have a recursive function but did not use the return value from the recursive call here:
PHP
if(is_dir($dir.DIRECTORY_SEPARATOR.$ff)) {
    listFolderFiles($dir.DIRECTORY_SEPARATOR.$ff);
}
When the start directory does not contain any files, the returned array is empty. Otherwise, it will contain only files from that (the start) directory.

So you have either to append the items from the returned array to the local array or rewrite your code to pass the array as parameter and operate on that. Using a global array should work too.

Try this (untested):
PHP
if(is_dir($dir.DIRECTORY_SEPARATOR.$ff)) {
    $sub_arr = listFolderFiles($dir.DIRECTORY_SEPARATOR.$ff);
    $arr = array_merge($arr, $sub_arr);
}
 
Share this answer
 
Comments
Hitesh Rohilla 15-Dec-17 6:54am    
Nice trick... but it is giving me following warnings

Warning: array_merge(): Argument #2 is not an array in <path> on line <line_number>
Warning: array_push() expects parameter 1 to be array, null given in <path> on line <line_number>
Jochen Arndt 15-Dec-17 7:11am    
I have not tested it, but it should work that way.

Especially the 2nd warning seems not to be related to the code shown in your question.

Inspect the lines mentioned in the warnings.

However, a better method would be passing the array by reference to the recursive function:
listFolderFiles($dir, &$arr)

Then you can push to that or just use $arr[] = $dir.DIRECTORY_SEPARATOR.$ff;
Hitesh Rohilla 15-Dec-17 7:18am    
by doing so it again re-declares that array while calling this function and cause the same issue.

However, I just have solved my issue with another trick. will share it as solution right away :)
Jochen Arndt 15-Dec-17 7:25am    
If &$arr has been specified as function parameter, there will be no re-declaration when using $arr in the function body because the '&' is the pass-by-reference operator.
Hitesh Rohilla 17-Dec-17 5:28am    
Actually, I tried that but won't worked as expected
So as a solution what I did is I defined a global string and concet all the outputs of the path string to that global string along with some charecter at the end of every string. I chose pipe "|" as my charecter.

After the process of
listFolderFiles()
function ends I remove last pipe "|" charecter and explode the string to become an array. So this way I have all the path in an array. After using this I clear the global string so that it can be reused freshly by other processes.

Though that's an indirect method but this workd like a charm for me :)
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900