1

I have a form that allows for dynamic duplication of the form fields. The form allows for file uploads and text input, so the data is sent in both $_POST and $_FILES arrays.

The the initial set of inputs look like this:

<input type="text" name="question[1][text]"  />
<input  type="file" name="question[1][file]"  /> 

<input type="text" class="a" name="answer[1][text][]"  /> 
<input  type="file" name="answer[1][file][]"  /> 

When duplicated the fields are incremented, they look like this:

<input type="text" name="question[2][text]"  />
<input  type="file" name="question[2][file]"  /> 

<input type="text" class="a" name="answer[2][text][]"  /> 
<input  type="file" name="answer[2][file][]"  /> 

To complicate matters, the "answer" form fields can also be duplicated (thus the [] at the end of the 'answer' name array.

How can I parse the posted $_FILES array? I have tried something like this:

foreach ($_FILES['question'] as $p_num)
{ 
  echo  $p_num['file']['name'];

    foreach ($_FILES['answer'] as $a_num)
    { 
      echo  $a_num['file']['name'];
    }

}

but I get an "Undefined index: file... " error. How can I parse out the posted values.

4
  • 1
    Possible. Use print_r($_FILES) and print_r($_POST) to devise a method to make it match. $_FILES has an overriding array structure. So, rename else. Commented Dec 23, 2010 at 7:18
  • thanks mario, I am looking into this. Commented Dec 23, 2010 at 7:27
  • 1
    If you include some sample output from print_r($_FILES) and print_r($_POST) we could probably help you. Commented Dec 29, 2010 at 3:26
  • @GWW I have saved a temp script here: superuntitled.com/temp.php <-- when you submit the form, I have var_dump of both $_POST and $_FILES Commented Dec 29, 2010 at 4:19

4 Answers 4

3
+200

updated

form:

<form method="post" enctype="multipart/form-data">
<input type="text" name="question[1][text]"  value="AAA"/>
<input type="file" name="question[1][file]"  />
<input type="text" name="answer[1][text][0]" value="bbb" />
<input type="file" name="answer[1][file][0]"  />
<input type="text" name="answer[1][text][1]" value="ccc" />
<input type="file" name="answer[1][file][1]"  />
<input type="submit"/>

php:

$rtn = array();
foreach ($_POST['question'] as $key=>$arr)
{
  if (!isset($rtn[$key])) 
  {
    $rtn[$key] = array('question'=>'', 'answer'=>array());
  }
  $rtn[$key]['question'] = $arr['text'];


  $tmp = array();
  foreach ($_FILES['question'] as $fkey=>$farr)
  {
    $tmp[$fkey] = $farr[$key]['file'];
  }
  $rtn[$key]['question_file']  = $tmp;

  $rtn[$key]['answer']['text'] = $_POST['answer'][$key]['text'];
}

foreach ($_FILES['answer'] as $key=>$arr)
{
  foreach ($arr as $answer_idx=>$farr)
  {
    foreach ($farr as $file_index=>$file)
    {
      $rtn[$answer_idx]['answer_file'][$file_index][$key] = $file;
    }
  }
}

output (upload using test.txt)

Array
(
    [1] => Array
        (
            [question] => AAA
            [answer] => Array
                (
                    [text] => Array
                        (
                            [0] => bbb
                            [1] => ccc
                        )

                )

            [question_file] => Array
                (
                    [name] => test.txt
                    [type] => text/plain
                    [tmp_name] => /tmp/phpqef5eL
                    [error] => 0
                    [size] => 0
                )

            [answer_file] => Array
                (
                    [file] => Array
                        (
                            [name] => Array
                                (
                                    [0] => test.txt
                                    [1] => test.txt
                                )

                            [type] => Array
                                (
                                    [0] => text/plain
                                    [1] => text/plain
                                )

                            [tmp_name] => Array
                                (
                                    [0] => /tmp/phpc2sdMs
                                    [1] => /tmp/phpzKNnja
                                )

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

                            [size] => Array
                                (
                                    [0] => 0
                                    [1] => 0
                                )

                        )

                )

        )

)
Sign up to request clarification or add additional context in comments.

3 Comments

thanks ajreal, i did not include this in my question, but they are most definitely in my code!
@superUntitled - mention before, <form action="temp2.php" method="post"> is incomplete, try <form action="temp2.php" method="post" enctype="multipart/form-data">
+1 for catching that! I have updated the file, but the $rtn array is empty.
2

PHP doesn't seem to like it when you upload files with filenames specified in multi-dimensional array format. Given that the POST and FILEs data are kept completely seperate in PHP, you should rejigger your form. The "question[1]" format is ok, but not "question[1][file]". Rather, try for something like:

<input type="text" name="question[1][text]"  />
<input  type="file" name="file[1]"  /> 

<input type="text" name="question[2][text]"  />
<input  type="file" name="file[2]"  /> 

As long as you keep the same index value for the file fields and all the other fields, can access the files during form processing like this:

foreach(array_keys($_POST['question']) as $key {
     $file_is = $_FILES['file'][$key]['tmp_name'];
     $question_text = $_POST['question][$key]['text'];
}

1 Comment

Thanks Marc, I am trying this out.
0

PHP "reorders" the $_FILES array in an undesirable way. If you visit the PHP manual, at the page discussing multiple file uploads:

http://www.php.net/manual/en/features.file-upload.multiple.php

You can find a big variety of code snippets in the page comments, all dealing with this annoyance. Most comments are about that, actually!

Comments

0

The PHP $_FILES array gets crazy when you're dealing with more than one file at a time. It's worse when you're dealing with multiple inputs that can each take multiple files. I wrote a library that takes the $_FILES array and gives you back a copy of it rearranged the way you were imagining.

In fact, the situation that finally made me write a robust solution for the problem was very much like yours. See the section in the readme about dealing with multiple fields that take multiple files.

Install tvanc/files-array-organizer

composer require tvanc/files-array-organizer

Organize $_FILES

With some minor adjustment to your code you can loop over the files like you were trying to do.

use tvanc\FilesArrayOrganizer\FilesArrayOrganizer;

// Use composer's autoload.php
require 'vendor/autoload.php';

$organizedFiles = FilesArrayOrganizer::organize($_FILES);

foreach ($organizedFiles['question'] as $q_index => $question)
{ 
    echo  $question['file']['name'];

    foreach ($organizedFiles['answer'][$q_index]['file'] as $answer_file)
    { 
        echo  $answer_file['name'];
    }

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.