mannyson Posted August 29, 2015 Share Posted August 29, 2015 Here's the deal. I am getting into uploading multiple images with a record details. Image file paths are stored in "images" table and records are stored in "records" table. They both work fine separately. I am just having issue using both of them together since "foreach loop" is involved. I want to make sure the image is uploaded and check for errors before inserting the image and record details. Since this for uploading "multiple files", all this checking for errors is inside "foreach loop". It will insert the images fine, but it will also insert the record details multiple times(depending on the images attached) in the records table. If I insert the record details outside the loop, it'll insert only once but then it'll insert the data with or without the images attached. Here's a basic set up of what I am talking about . I removed the extra code. I just would like to know where I can place the insert into records code relative to the foreach loop so that It checks the errors for file uploads and inserts details in to the database after that. if(isset($_POST['submit']) { $record_name = trim($_POST['record_name']); $record_details = trim($_POST['record_details']); $record_type = trim($_POST['record_type']); $date = date('Y-m-d H:i:s'); if(empty($record_name)) { echo 'record name is required!'; } else if(empty($record_details)) { $error = 'record details are required!'; } else if(empty($record_type)) { $error = 'Type is required!'; } else { if(isset($_FILES['files'])){ $userdir = $_SERVER['DOCUMENT_ROOT'] .'/comp/images/'; if(!is_dir($userdir)){ mkdir($userdir, 0775, true); } foreach($_FILES['files']['tmp_name'] as $key => $tmp_name ){ if(is_uploaded_file($_FILES['files']['tmp_name'][$key])) { if(in_array($type, $allowed)) { try { $insert_image = $db->prepare("INSERT INTO images(record_id, image_path, date) VALUES(:record_id, :image_path, :date)"); $insert_image->bindParam(':record_id', $record_id); $insert_image->bindParam(':image_path', $image_path); $insert_image->bindParam(':date', $date_added); $result_image = $insert_image->execute(); if($result_image == false) { echo 'There was a problem!'; } else { move_uploaded_file($temp, $file_path); echo 'Your image has been saved.'; } $insert_record = $db->prepare("INSERT INTO records(record_name, record_type, record_details, date) VALUES(:record_name, :record_type, :record_details, :date)"); $insert_record->bindParam(':record_name', $record_name); $insert_record->bindParam(':record_type', $record_type); $insert_record->bindParam(':record_details', $record_details ); $insert_record->bindParam(':date', $date); $result_record = $insert_record->execute(); if($result_record == true) { echo 'Your record has been saved.'; } else { $error = 'record not added!'; } } catch(Exception $e) { $error = die($e->getMessage()); } } else { echo 'You have uploaded a forbidden extension!'; } } else { echo 'File is empty!'; } } } } } Quote Link to comment Share on other sites More sharing options...
QuickOldCar Posted August 30, 2015 Share Posted August 30, 2015 (edited) After if(in_array($type, $allowed)) { save them as an array end loop check for not an empty array build your sql query statement using implode() from the array You could also build an array the failed ones and any error messages. I noticed you use die(), if you do that the loop will stop and not do anything else. Edited August 30, 2015 by QuickOldCar Quote Link to comment Share on other sites More sharing options...
mannyson Posted August 30, 2015 Author Share Posted August 30, 2015 After if(in_array($type, $allowed)) { save them as an array end loop check for not an empty array build your sql query statement using implode() from the array You could also build an array the failed ones and any error messages. I noticed you use die(), if you do that the loop will stop and not do anything else. Can you provide an example with the array? It would really help. Thanks. Quote Link to comment Share on other sites More sharing options...
iarp Posted August 30, 2015 Share Posted August 30, 2015 Just to clarify something, you're inserting 1 record and multiple images correct? If so, you would insert into the records table first to obtain the record id and then insert the multiple images using the for loop. If my assumption is correct then your $insert_record section should be moved to before the "if(isset($_FILES['files'])){" part. $record_id would come from the id of the record that was inserted using $insert_record-lastInsertId() after the $insert_record->execute() statement. Quote Link to comment Share on other sites More sharing options...
mannyson Posted August 30, 2015 Author Share Posted August 30, 2015 (edited) Just to clarify something, you're inserting 1 record and multiple images correct? If so, you would insert into the records table first to obtain the record id and then insert the multiple images using the for loop. If my assumption is correct then your $insert_record section should be moved to before the "if(isset($_FILES['files'])){" part. $record_id would come from the id of the record that was inserted using $insert_record-lastInsertId() after the $insert_record->execute() statement. Yes I can do that and I have done it. But that's not the solution I am looking for it. I am inserting 1 record with option to choose multiple images. The record will insert if I have it outside the loop. And the images will insert if I have selected them. The issue is that if the selected image(s) gives an error, the record itself will insert anyways I just want to make sure that if errors are produced by the selected images, that to not insert the record data into the table. That's all. Edited August 30, 2015 by mannyson Quote Link to comment Share on other sites More sharing options...
mac_gyver Posted August 30, 2015 Share Posted August 30, 2015 (edited) validation of the form data and using the form data are two different concerns and have to be separated. you have to validate the form data first, then use the resulting error information to determine what the rest of the code should do. if you use an array to hold your validation errors, your logic will be easier to write. create an array to hold the errors - $errors = array(); to added errors to the array - $errors[] = "some validation error message"; to test if there are not or are errors at any point in your program flow - if(empty($errors)){} - no errors or - if(!empty($errors)){} - there are errors. Edited August 30, 2015 by mac_gyver Quote Link to comment Share on other sites More sharing options...
iarp Posted August 30, 2015 Share Posted August 30, 2015 (edited) Yes I can do that and I have done it. But that's not the solution I am looking for it. I am inserting 1 record with option to choose multiple images. The record will insert if I have it outside the loop. And the images will insert if I have selected them. The issue is that if the selected image(s) gives an error, the record itself will insert anyways I just want to make sure that if errors are produced by the selected images, that to not insert the record data into the table. That's all. Ah ha, you could make good use of transactions for this issue. I have taken mac_gyver's suggestion of using $errors along with using PDO's transaction system to keep track of errors and choosing whether or not to commit to the database or rollBack. Making use of $errors allows you to collect all possible errors that occurred with the form, display that to the user so that they could potentially fix all problems with a single form submission. You're original script would mean they would continuously have to resubmit the form checking every field individually which is very annoying if you run into it in real life. <?php if (isset($_POST['submit']) { $record_name = trim($_POST['record_name']); $record_details = trim($_POST['record_details']); $record_type = trim($_POST['record_type']); $date = date('Y-m-d H:i:s'); $errors = array(); if (empty($record_name)) { $errors[] = 'record name is required!'; } if (empty($record_details)) { $errors[] = 'record details are required!'; } if (empty($record_type)) { $errors[] = 'Type is required!'; } $db->beginTransaction(); $insert_record = $db->prepare("INSERT INTO records(record_name, record_type, record_details, date) VALUES(:record_name, :record_type, :record_details, :date)"); $insert_record->bindParam(':record_name', $record_name); $insert_record->bindParam(':record_type', $record_type); $insert_record->bindParam(':record_details', $record_details ); $insert_record->bindParam(':date', $date); if (!$insert_record->execute()) { $errors[] = 'record not added!'; } $record_id = $db->lastInsertId(); if (!empty($_FILES['files'])) { $userdir = $_SERVER['DOCUMENT_ROOT'] . '/comp/images/'; if (!is_dir($userdir)){ mkdir($userdir, 0775, true); } foreach($_FILES['files']['tmp_name'] as $key => $tmp_name ){ $file_path = $userdir . $tmp_name; if (is_uploaded_file($_FILES['files']['tmp_name'][$key])) { if (in_array($type, $allowed)) { try { $insert_image = $db->prepare("INSERT INTO images(record_id, image_path, date) VALUES(:record_id, :image_path, :date)"); $insert_image->bindParam(':record_id', $record_id); $insert_image->bindParam(':image_path', $file_path); $insert_image->bindParam(':date', $date); if (!$insert_image->execute()) { $errors[] = 'There was a problem!'; } else { move_uploaded_file($tmp_name, $file_path); echo 'Your image has been saved.'; } } catch(Exception $e) { $error[] = die($e->getMessage()); } } else { $errors[] = 'You have uploaded a forbidden extension!'; } } else { $errors[] = 'File is empty!'; } } } else { $errors[] = 'No files supplied'; } # If the errors array is empty then commit all of the changes we've made above, to the database. # Otherwise rollback all changes/inserts and undo everything we just did. if (empty($errors)) { $db->commit(); } else { $db->rollBack(); } } Edited August 30, 2015 by iarp Quote Link to comment Share on other sites More sharing options...
mannyson Posted August 30, 2015 Author Share Posted August 30, 2015 (edited) Ah ha, you could make good use of transactions for this issue. I have taken mac_gyver's suggestion of using $errors along with using PDO's transaction system to keep track of errors and choosing whether or not to commit to the database or rollBack. Making use of $errors allows you to collect all possible errors that occurred with the form, display that to the user so that they could potentially fix all problems with a single form submission. You're original script would mean they would continuously have to resubmit the form checking every field individually which is very annoying if you run into it in real life. <?php if (isset($_POST['submit']) { $record_name = trim($_POST['record_name']); $record_details = trim($_POST['record_details']); $record_type = trim($_POST['record_type']); $date = date('Y-m-d H:i:s'); $errors = array(); if (empty($record_name)) { $errors[] = 'record name is required!'; } if (empty($record_details)) { $errors[] = 'record details are required!'; } if (empty($record_type)) { $errors[] = 'Type is required!'; } $db->beginTransaction(); $insert_record = $db->prepare("INSERT INTO records(record_name, record_type, record_details, date) VALUES(:record_name, :record_type, :record_details, :date)"); $insert_record->bindParam(':record_name', $record_name); $insert_record->bindParam(':record_type', $record_type); $insert_record->bindParam(':record_details', $record_details ); $insert_record->bindParam(':date', $date); if (!$insert_record->execute()) { $errors[] = 'record not added!'; } $record_id = $db->lastInsertId(); if (!empty($_FILES['files'])) { $userdir = $_SERVER['DOCUMENT_ROOT'] . '/comp/images/'; if (!is_dir($userdir)){ mkdir($userdir, 0775, true); } foreach($_FILES['files']['tmp_name'] as $key => $tmp_name ){ $file_path = $userdir . $tmp_name; if (is_uploaded_file($_FILES['files']['tmp_name'][$key])) { if (in_array($type, $allowed)) { try { $insert_image = $db->prepare("INSERT INTO images(record_id, image_path, date) VALUES(:record_id, :image_path, :date)"); $insert_image->bindParam(':record_id', $record_id); $insert_image->bindParam(':image_path', $file_path); $insert_image->bindParam(':date', $date); if (!$insert_image->execute()) { $errors[] = 'There was a problem!'; } else { move_uploaded_file($tmp_name, $file_path); echo 'Your image has been saved.'; } } catch(Exception $e) { $error[] = die($e->getMessage()); } } else { $errors[] = 'You have uploaded a forbidden extension!'; } } else { $errors[] = 'File is empty!'; } } } else { $errors[] = 'No files supplied'; } # If the errors array is empty then commit all of the changes we've made above, to the database. # Otherwise rollback all changes/inserts and undo everything we just did. if (empty($errors)) { $db->commit(); } else { $db->rollBack(); } } Yes that does seem to work. Now the only issue I have is the "f (is_uploaded_file($_FILES['files']['tmp_name'][$key]))". Despite having a file selected, it will return the "else(file is empty)" error. It won't process beyond that. Now if I remove that check, it'll process. But then it'll go to the next error "You have uploaded a forbidden extension!" on submit, even if a file is not selected. I think the check "if (!empty($_FILES['files'])) " is not really doing it's job. Edited August 30, 2015 by mannyson Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.