$_FILES Array Structure

I like to use the format formname[fieldName] on forms because then it stores all the values in array, which makes processing multiple forms easier.

However I’ve ran into some issue handling file uploads in this format.

When I use the format testform[foo] I get the following array…


Array
(
    [testform] => Array
        (
            [name] => Array
                (
                    [foo] => bookmarks.html
                )

            [type] => Array
                (
                    [foo] => text/html
                )

            [tmp_name] => Array
                (
                    [foo] => C:\\WINDOWS\\TEMP\\php3C.tmp
                )

            [error] => Array
                (
                    [foo] => 0
                )

            [size] => Array
                (
                    [foo] => 644563
                )

        )

)


When I use the format testform-foo I get the following array which is much easier to handle.


Array
(
    [testform-foo] => Array
        (
            [name] => bookmarks.html
            [type] => text/html
            [tmp_name] => C:\\WINDOWS\\TEMP\\php3D.tmp
            [error] => 0
            [size] => 644563
        )

)


Any ways to use my prefered naming structure while still indexing the array by fieldname?


$my_files = array();


foreach ($_FILES['testform']['error'] as $key => $error) {
    $my_files[$key]['name'] = $_FILES['testform']['name'][$key];
    $my_files[$key]['type'] = $_FILES['testform']['type'][$key];
    $my_files[$key]['tmp_name'] = $_FILES['testform']['tmp_name'][$key];
    $my_files[$key]['error'] = $_FILES['testform']['error'][$key];
    $my_files[$key]['size'] = $_FILES['testform']['size'][$key];
}
print_r($my_files);

Perfect! Much appreciated!

Hi.

I am looking for a way to transform the $_FILES array into an array of the following structure independent of the name value of the input tag.


name="foo"

-> $aUploads = array(
    'foo' => new UploadFile(size, name,...)
)

name="foo[bar]"

-> $aUploads = array(
    'foo' => array(
        'bar' => new UploadFile(size, name,...)
    )
)

name="foo[bar][baz]"

-> $aUploads = array(
    'foo' => array(
        'bar' => array(
            'baz' => new UploadFile(size, name,...)
        )
    )
)

Of course it has to work for multiple file uloads, too.

Any approaches?

Basti

my little brain cant think of anything more efficient than this. a lot of loops and recursion going on here…


function walk($arr, $key) {
    $ret = array();
    foreach ($arr as $k => $v) {
        if (is_array($v)) {
            $ret[$k] = walk($v, $key);
        } else {
            $ret[$k][$key] = $v;
        }
    }
    return $ret;
}



$arr = array();
foreach ($_FILES as $name => $values) {

    // init for array_merge
    if (!isset($arr[$name])) {
        $arr[$name] = array();
    }

    if (!is_array($values['error'])) {
        // normal syntax
        $arr[$name] = $values;
    } else {
        // html array feature
        foreach ($values as $attribute_key => $attribute_values) {
            $arr[$name] = array_merge_recursive($arr[$name], walk($attribute_values, $attribute_key));
        }
    }
}

print_r($arr);

it supports both non html array syntax, as well as html array syntax even with multidim arrays, and will standardize them into a common(but repetative) format. just like you asked for. it doesnt immediately allow for you to create the objects. another walk will need to be performed. i cant think of any way around that short of using eval().

the resulting array could be walked again with yet another recursive function to instantiate your objects.


function make_objects($arr) {
    $ret = array();
    foreach ($arr as $k => $v) {
        if (is_array($v)) {
            $ret[$k] = make_objects($v);
        } else {
            return new UploadFile($arr['size'], $arr['name'], 'etc...');
        }
    }
    return $ret;
}
print_r(make_objects($arr));

whew.

id love to see a better way to do this while supporting arbitrary nesting depth. maybe im approaching it wrong.

I know this post if old but I have a good solution for this problem:

$files = array();
foreach ($_FILES as $key_ => $file) {
	foreach ($file as $key => $data) {
		foreach ($data as $model => $fields) {
			if (is_array($fields)) {
				foreach ($fields as $field => $value) {
					if (is_array($value)) {
						foreach ($value as $k => $v) {
							$files[$key_][$model][$field][$k][$key] = $v;
						}
					} else {
						$files[$key_][$model][$field][$key] = $value;
					}
				}
			} else {
				$files[$key_][$model][$key] = $fields;
			}
		}
	}
}

var_dump($files);