0

I have a form with multiple rows (rows from SQL, iterated and generated the form). Each of those rows has a multiple file input field (the user can upload 0, 1 or multiple in each input). Files are being uploaded correctly, with correctly assigned new file names (file names are generated based on each row SQL ID). Then after user click the SUBMIT, the file names are added to a column in SQL table.

The form can generate 0, 1 ... 100 rows, so to prevent the php iterating through all those 100s rows, and executing an UPDATE or rows where it is not needed, I only execute the UPDATE on rows that the user has touched.

My problem is when I upload a single or multiple file on a singular file input field (a row), then everything works as expected. However, when I try to upload 1 or more files in separate file inputs fields, then something strange happens in SQL, the files upload to the server are all OK, but database goes weird.

  1. The first input (row) will have correct number of files with correct names, as desired.
  2. Every next input (row, in the database after the UPDATE) will have the all the file names from all previous inputs, plus the ones that were uploaded for the specific input... if that makes sense... Here illustration:
Input 1: input1file1.jpg, input1file2.jpg
Input 2: input1file1.jpg, input1file2.jpg, input2file1.jpg

Because each input field can take multiple files, so the input name is already an array name='attachment[]'.

To distinguish between those input fields, I add row ID to file name.

Here is my code, I cannot work out what is causing it?

Form:

<form enctype="multipart/form-data" method="post">
...
php iteration:
  <div>
    <input class="hasChanged" name="attachments'.$row['pk'].'[]" type="file" multiple>
    <input value="'.$row['existing_attachments'].'" id="updateAttachmentValue'.$row['pk'].'" name="existingAttachments'.$row['pk'].'">
  </div>
...
</form>

PHP:

//iterate
foreach($_POST['foo_field'] as $key => $n){
  if(in_array($upl[$key], $touched_rows)){
    $aID = $upl[$key];
    $prevAttachments = (empty($_POST['existingAttachments'.$aID]) || $_POST['existingAttachments'.$aID]=='|') ? NULL : $_POST['existingAttachments'.$aID];
    $attachments = NULL;
    if(count($_FILES['attachments'.$aID]['name']) > 0){
      if(!empty($_FILES['attachments'.$aID])){
        for($i=0; $i<count($_FILES['attachments'.$aID]['name']); $i++){//Loop through each file
          $tmpFilePath = $_FILES['attachments'.$aID]['tmp_name'][$i];//Get the temp file path
          if($tmpFilePath != ''){//Make sure we have a filepath
            $shortname = 'AP-'.$aID.'-'.$_FILES['attachments'.$aID]['name'][$i];//save the filename
            $filePath = $attachmentDirectory.'\AP-'.$aID.'-'.$_FILES['attachments'.$aID]['name'][$i];//save the url and the file
            if(move_uploaded_file($tmpFilePath, $filePath)){//Upload the file into the correct dir
              $files[] = $shortname;
            }
            $attachments = implode('|',$files);
          }
        }
      }
    }
    $prevAttachments = !empty($attachments) ? $attachments.'|'.$prevAttachments : $prevAttachments;
    try{
      $stmt = $conn->prepare("EXEC [name].[dbo].[table] :p1,:p2");
      $stmt->bindParam(':p1', $upl[$key], PDO::PARAM_INT);
      $stmt->bindParam(':p2', $prevAttachments, PDO::PARAM_STR);
      $stmt->execute();
    }catch(PDOException $e){ echo 'ERROR: ' . $e->getMessage();}
  }
}
4
  • It sounds like you need to set $files = array(); at the beginning of each "row". Commented Jan 5, 2022 at 17:58
  • 2
    It seems that you are storing multiple attachment names in a single column in your database, though I'm not familiar with the query as you've posted it. If you are storing multiple values in one column, I'd suggest this will be a source of future problems and you should really consider storing them in a separate table with a suitable link. "Database normalisation" is the term used. Commented Jan 5, 2022 at 18:09
  • See Is storing a delimited list in a database column really that bad Commented Jan 5, 2022 at 19:28
  • @cOle2 Thank you, this has fixed the issue. Please submit as the answer, I will accept it. Commented Jan 6, 2022 at 11:19

1 Answer 1

0

In your code you never set or reset $files so that's why the value contains all previous files.

You should set $files = array(); at the beginning of each "row" to ensure $files only contains values for the specific row.

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

1 Comment

I assumed $files[] in $files[] = $shortname; is always reset, because the square brackets are blank.

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.