Hitesh Rohilla Ответов: 2

Невозможно вернуть массив, несколько массивов в одной переменной в PHP


ПОСТАНОВКА ЗАДАЧИ

У меня есть 1000 файлов, хранящихся в структуре папок в следующем формате

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


На основе определенных параметров мне нужно выбрать одну или несколько папок верхнего уровня и сжать все или выбранные файлы из нее в один zip-файл на ходу и предоставить его пользователю для загрузки. Теперь чтобы сжать все эти файлы я использую метод показанный в решении этого вопроса на StackOverflow Загрузите несколько файлов в виде zip-файла с помощью php - Stack Overflow[^] .

этот метод требует массива, имеющего полный путь к файлам, которые нужно сжать, и вот где я застрял.

СИТУАЦИЯ

Это довольно странно, с чем я сейчас сталкиваюсь. У меня есть функция, которая возвращает массив всех файлов в предоставленной папке и ее подпапке. Теперь проблема в том, когда я есть print_r($ОБР) внутри функции, где $прибытие имеет все данные он показывает мне данные но когда я назначаю эти данные переменной вызывающей функции и print_r($переменная) это пустой массив();

Я копнул глубже и заметил, что $variable имеет несколько массивов, назначенных в нем, возможно, потому, что он рекурсивен.

Позвольте мне привести несколько примеров кода...

<?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


?>


теперь я внимательно наблюдал за выходом print_r($ОБР); это что-то вроде этого

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> )


ясно, что вы можете видеть, что эта переменная имеет в себе 4 массива, и это не повторяющиеся данные, так как каждый массив имеет разные элементы и разное количество элементов в них. Я также пробовал работать с глобальной переменной $arrGlobal но результат тот же. когда я подсчитываю длину массива (), он дает мне разные длины следующим образом

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

// OUTPUT
3234


Я думал, что это массив массива, поэтому я попробовал print_r($arr[0]) и это дало мне предупреждение.

<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


Что я уже пробовал:

Надеюсь, я все здесь описал. Я предполагаю, что поскольку функция рекурсивна, то эта проблема возникает. Пожалуйста, помогите мне решить эту проблему как можно скорее.

2 Ответов

Рейтинг:
8

Hitesh Rohilla

Поэтому в качестве решения я определил глобальную строку и соединил все выходные данные строки пути с этой глобальной строкой вместе с некоторым charecter в конце каждой строки. Я выбрал трубу "|" в качестве своего сопровождающего.

После того как процесс

listFolderFiles()
функция заканчивается тем, что я удаляю последний канал "|" charecter и взрываю строку, чтобы она стала массивом. Таким образом, у меня есть весь путь в массиве. После этого я очищаю глобальную строку, чтобы она могла быть повторно использована другими процессами.

Хотя это косвенный метод, но эта работа похожа на очарование для меня :)


Рейтинг:
2

Jochen Arndt

У вас есть рекурсивная функция, но вы не использовали возвращаемое значение из рекурсивного вызова здесь:

if(is_dir($dir.DIRECTORY_SEPARATOR.$ff)) {
    listFolderFiles($dir.DIRECTORY_SEPARATOR.$ff);
}
Если начальный каталог не содержит никаких файлов, возвращаемый массив пуст. В противном случае он будет содержать только файлы из этого (начального) каталога.

Таким образом, вы должны либо добавить элементы из возвращаемого массива в локальный массив, либо переписать свой код, чтобы передать массив в качестве параметра и работать с ним. Использование глобального массива тоже должно работать.

Попробуйте это (непроверено):
if(is_dir($dir.DIRECTORY_SEPARATOR.$ff)) {
    $sub_arr = listFolderFiles($dir.DIRECTORY_SEPARATOR.$ff);
    $arr = array_merge($arr, $sub_arr);
}


Hitesh Rohilla

Хороший трюк... но он дает мне следующие предупреждения

Предупреждение: array_merge(): Аргумент #2 не является массивом в <path> on line <line_number>
Предупреждение: array_push() ожидает, что параметр 1 будет массивом, null заданным в <path> on line <line_number>

Jochen Arndt

Я не проверял его, но он должен работать именно так.

Особенно 2-е предупреждение, по-видимому, не связано с кодом, показанным в вашем вопросе.

Проверьте линии, упомянутые в предупреждениях.

Однако лучшим методом была бы передача массива по ссылке на рекурсивную функцию:

listFolderFiles($dir, &$arr)

Затем вы можете нажать на это или просто использовать $arr[] = $dir.DIRECTORY_SEPARATOR.$ff;

Hitesh Rohilla

при этом он снова повторно объявляет этот массив при вызове этой функции и вызывает ту же проблему.

Однако я только что решил свою проблему с помощью другого трюка. поделюсь им как решением сразу же :)

Jochen Arndt

Если &$arr был указан в качестве параметра функции, то при использовании $arr в теле функции повторное объявление не будет выполнено, поскольку '&' является оператором pass-by-reference.

Hitesh Rohilla

На самом деле, я пробовал это сделать, но не получилось так, как ожидалось