Меня всегда мучал вопрос по поводу того, почему так устроен массив $_FILES в PHP, точнее то, почему он очень странным образом формирует его. В случае, если имена полей формы оформлены с использованием синтаксиса массива, $_REQUEST, $_GET или $_POST будут содержать правильное представление, но… такое использование не подходит для $_FILES!
Имеем форму:
При загрузке файлов через эту форму получаем массив $_FILES следующего вида:
Мне эта «фича» в большинстве случаев не подходит и кажется нелогичной. Простейшее решение — использовать простые (строковые) имена для полей типа «файл», например file_0, file_1, ..., file_N, но это не так удобно. Если, все-таки, вас интересует решение этой проблемы — читаем далее…
В autoprepend-файле или где-нибудь в момент инициализации вашего приложения стоит обработать массив $_FILE следующим образом:
В итоге имеем более «логичный» миссив:
Разместил это решение комментарием в официальной документации, т.к. вопросов много, а конкретного примера нет. Но, на момент публикации здесь его там пока ещё не появилось (не знаю, появится ли?).
Спасибо за внимание, надеюсь кому-нибудь пригодится.
UPD: Глядя на то, как мои слова «В autoprepend-файле или где-нибудь в момент инициализации вашего приложения стоит обработать массив $_FILE» и перезапись в коде массива $_FILES вызвали некоторое негодование некоторой части сообщества, заявляю: это пример того, как можно реализовать необходимый функционал, и я не призываю использовать данный код «как есть» в боевых проектах.
Проблема
Имеем форму:
<form action="" method="post" enctype="multipart/form-data"> <input type="file" name="oneLevel[]"> <input type="file" name="oneLevel[]"> <input type="submit"> </form>
При загрузке файлов через эту форму получаем массив $_FILES следующего вида:
array( 'files' => array ( 'name' => array ( 0 => 'Lighthouse.jpg', 1 => 'Hydrangeas.jpg', ), 'type' => array ( 0 => 'image/jpeg', 1 => 'image/jpeg', ), 'tmp_name' => array ( 0 => '/tmp/phpQR67Qp', 1 => '/tmp/phpJjnAHA', ), 'error' => array ( 0 => 0, 1 => 0, ), 'size' => array ( 0 => 561276, 1 => 595284, ), ), )
Мне эта «фича» в большинстве случаев не подходит и кажется нелогичной. Простейшее решение — использовать простые (строковые) имена для полей типа «файл», например file_0, file_1, ..., file_N, но это не так удобно. Если, все-таки, вас интересует решение этой проблемы — читаем далее…
Решение
В autoprepend-файле или где-нибудь в момент инициализации вашего приложения стоит обработать массив $_FILE следующим образом:
/** * Рекурсивная функция для реструктуризации массива * * @param array $arrayForFill Массив для заполнения. * Этот массив будет содержать "правильное" * представление $_FILES * @param string $currentKey Ключ текущей позиции * @param mixed $currentMixedValue Значение текущей позиции * @param string $fileDescriptionParam Текущий параметр описания файла * (name, type, tmp_name, error или size) * @return void */ function rRestructuringFilesArray(&$arrayForFill, $currentKey, $currentMixedValue, $fileDescriptionParam) { if (is_array($currentMixedValue)) { foreach ($currentMixedValue as $nameKey => $mixedValue) { rRestructuringFilesArray($arrayForFill[$currentKey], $nameKey, $mixedValue, $fileDescriptionParam); } } else { $arrayForFill[$currentKey][$fileDescriptionParam] = $currentMixedValue; } } // массив, в котором будем формировать "правильный" $_FILES $arrayForFill = array(); // первый уровень проходим без изменения foreach ($_FILES as $firstNameKey => $arFileDescriptions) { // а вот со второго уровня интерпритатор делает то, // что мне в большинстве случаев не подходит foreach ($arFileDescriptions as $fileDescriptionParam => $mixedValue) { rRestructuringFilesArray($arrayForFill, $firstNameKey, $_FILES[$firstNameKey][$fileDescriptionParam], $fileDescriptionParam); } } // перегружаем $_FILES сформированным массивом $_FILES = $arrayForFill;
В итоге имеем более «логичный» миссив:
array( 'files' => array ( 0 => array ( 'name' => 'Lighthouse.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/tmp/phpKNqlsc', 'error' => 0, 'size' => 561276, ), 1 => array ( 'name' => 'Hydrangeas.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/tmp/phpB8X3E8', 'error' => 0, 'size' => 595284, ), ), )
Разместил это решение комментарием в официальной документации, т.к. вопросов много, а конкретного примера нет. Но, на момент публикации здесь его там пока ещё не появилось (не знаю, появится ли?).
Спасибо за внимание, надеюсь кому-нибудь пригодится.
UPD: Глядя на то, как мои слова «В autoprepend-файле или где-нибудь в момент инициализации вашего приложения стоит обработать массив $_FILE» и перезапись в коде массива $_FILES вызвали некоторое негодование некоторой части сообщества, заявляю: это пример того, как можно реализовать необходимый функционал, и я не призываю использовать данный код «как есть» в боевых проектах.