This week I finally lost patience with the mental gymnastics required to unpack the $_FILES array that PHP provides when uploading files with POST. I knocked up this quick function to reorganise the data into something I could work with.
The original $_FILES array provides information relating to a file upload in an array containing elements for name, temporary name, type, size and error. This is workable for a single file upload, but for mutiple files uploaded this way, the single elements for name, size, etc., are replace by arrays of names, sizes, types etc.
Not only must one differentiate between single and multiple file uploads, but the data for multiple files is spread across an array of arrays, and has to be linked together using a common index. No foreach
here.
This whole approach is difficult to navigate, and prone to error.
This function returns a reorganised array, starting with the HTML field names at the top level, and an array of individual objects grouping all the related information together below. It looks something like this:
[ "fieldName1"=>[ fileObject1, fileObject2, fileObject3 ], "fieldName2"->[ fileObject4, fileObject5, fileObject6 ], ]Each file object contains the following properties:
name type size tmp_name error
The code
<?php
/**
* fixFiles.php
*
* Work through the $_FILES array, aggregating the various fields in different arrays into an
* array of arrays of objects.
*
* Usage:
* include("fixFiles.php");
* $newArray = fixFiles();
*
* Resulting structure:
*
* array, key: HTML field name
* array, key: numeric, one entry per uploaded file
* objects: properties: name, type, size, tmp_name, error
*
* @author Mike Whipps
* @copyright Copyright (c) 2021 Mike Whipps, littlevale.com
* @license MIT licence
*/
function fixFiles(?array $fileList = null):array {
$fileList = $fileList ?? $_FILES;
$fieldList = [];
foreach ($fileList as $field => $files) {
// Create a list of the HTML field names.
if (is_array($files['name'])) {
$fileDetails = [];
for ($i = 0; $i < sizeof($files['name']); $i++) {
// error 4 is No File Uploaded. Skip those.
if ($files['error'][$i] !== 4) {
$fileDetails[$i] = (object)[
'name' => $files['name'][$i],
'tmp_name' => $files['tmp_name'][$i],
'type' => $files['type'][$i],
'error' => $files['error'][$i],
'size' => $files['size'][$i]
];
}
}
$fieldList[$field] = $fileDetails;
} else {
$fieldList[$field] = [(object)$files];
}
}
return $fieldList;
}
I have it in mind to turn this into a PHP class so that it can be autoloaded. See the Projects page in days to come.
As usual, this code is provided 'as is' in the hope that someone will find it useful. I provide no warranty of any kind.