Loop through multiple field names - php

I've got the following input fields:
<input name="file1" type="file">
<input name="file2" type="file">
<input name="files[]" type="file" multiple>
I'm trying to figure out the best way to check which of the fields above are not empty and perform some DB action with the ones that have files in them.
I can check them each one manually like this but I am wondering if there is a better way to do this:
if(!empty($_FILES['file1']['name']) {
// Perform checks/etc for file1
}
if(!empty($_FILES['file2']['name']) {
// Perform checks/etc for file2
}
if(!empty($_FILES['files']['name'][0]) {
// Loop the array, perform checks/etc for each one
}

This will loop through all the files and tell you which ones are empty, and put the files that have content in the $submittedFiles array.
$submittedFiles = [];
foreach ($_FILES as $n => $f) {
if (!empty($f['name']) && !empty($f['name'][0])) {
$submittedFiles[] = $f;
} else {
echo $n.' is empty';
}
}
var_dump($submittedFiles);

Related

PHP Multiple Input Text and Input File Array

I have the following code Multiple text and type File Using an array to upload file and Text.
in this code, if I remove type file this code is working. but after use file is not work
Here is the Form
<form method="post" enctype="multipart/form-data">
<?php
$data_array = array('text','text2','file','file2');
foreach($data_array as $data_name){ ?>
<input type="hidden" name="data_name[]" value="<?php echo $data_name; ?>">
<?php if(strpos($data_name,'text') !== false){ ?>
<input name="data_value[]" type="text" />
<?php }
if(strpos($data_name,'file') !== false){ ?>
<input name="data_value[]" type="file" /> <?php }
} ?>
<input type="submit" name="submit" value="Add" />
</form>
Here is The Php Code, I Think More Improvement on $_FILE Part
if(isset($_POST['submit'])){
if(isset($_FILES['data_name'])){
foreach(array_combine($_FILES['data_name'],$_POST['data_value']) as $dataname => $datavalue){
$file_name = $_FILES['data_name']['name'];
echo file_name;
}
}
if(isset($_POST['data_name'])){
foreach(array_combine($_POST['data_name'],$_POST['data_value']) as $dataname => $datavalue){
echo $dataname.' - '.$datavalue;
}
}
}
Here is The Error of File..
Warning: array_combine(): Both parameters should have an equal number
of elements in pagename.php on line 25
Warning: Invalid argument supplied for foreach() in pagename.php on line 25
I Need Output Like This -
text = value
text2 = value2
file = file.jpg
file2 = file2.jpg
As stated explicitly in the error message, $_FILES['data_name'] and $_POST['data_value' are not the same size. (And I'm pretty sure the foreach is failing because the array_combine failed).
That is explained by you here: "if I remove type file this code is working. but after use file is not work".
If you want to use array_combine(), the arrays must be of the same size.
If you add a filter (eg if(strpos($data_name,'file') !== false)) the potential exists that the arrays will not match (as this problem indicates).
One approach would be to filter out the "data_name[]" inputs with the same condition as the "data_value[]" inputs.
Or the other way round: add an else on the above mentioned if that produces <input name="data_value[]" type="hidden" /> (notice the type). This will ensure the arrays are the same size. You will have to figure out what to do with these "dummy" inputs in the php code. Perhaps give them a value (like value="dummy") that you can test on.
replace your php-code with this:
function get_names_for_entity($name, $arr)
{
if (!empty($arr)) {
$ret = array_values(
array_filter(
$arr,
function ($itm) use ($name) {
return strpos($itm, $name) !== false;
}
)
);
} else {
$ret = [];
}
return $ret;
}
$names_a = [
'file' => get_names_for_entity('file', $_POST['data_name']),
'text' => get_names_for_entity('text', $_POST['data_name'])
];
if (isset($_POST['submit'])) {
if (isset($_POST['data_value'])) {
foreach ($_POST['data_value'] as $dataname_idx => $datavalue) {
echo $names_a['text'][$dataname_idx].' - '.$datavalue;
}
}
if (isset($_FILES['data_value'])) {
foreach ($_FILES['data_value']['name'] as $dataname_idx => $datavalue) {
$file_name = $_FILES['data_value']['name'][$dataname_idx];
echo $names_a['file'][$dataname_idx].' - '.$file_name;
}
}
}

Send radio selection to function along with textbox

I've got some code working that takes the text from my input box and moves it across to a function. I'm now trying to change it so I add another form element, a radio button and I want to access the choice within my functions.php file.
This is my current code which works for the post name, but what if I want to also grab the colours boxes that was selected too?
main.php
<?php
if (isset($_POST['submit'])) {
$data = $_POST['name']; // the data from the form input.
}
?>
...
<form action="/" method="post">
<input type="text" name="name" placeholder="Acme Corp"/>
<input name="colour" type="radio" value="red">Red<br>
<input name="colour" type="radio" value="blue">Blue<br>
<input name="colour" type="radio" value="green">Green<br>
<input type="submit" name="submit" value="Submit">
</form>
<img src="pngfile.php?data=<?php print urlencode($data);?>"
alt="png php file">
I guess I confused because currently it is calling this:
pngfile.php
<?php
require_once 'functions.php';
$inputData = urldecode($_GET['data']);
process($inputData);
exit;
?>
Which calls functions.php
<?php
function process($inputdata)
{
...
EDIT: What I have tried:
main.php [Change]
$data = $_POST['name'] && $_POST['colour']
But I'm not really sure how to progress.
Never trust user input. Sanitize and validate your inputs before using them.
This can be arranged better, but the basics are still true.
PHP Manual: filter_input_array()
PHP Manual: filter_var_array()
Small Function Library
function sanitizeArray($filterRules)
{
return filter_input_array(INPUT_POST, $filterRules, true)
}
function validateArray($filteredData, $validationRules)
{
return filter_var_array($filteredData, $validationRules, true);
}
function checkFilterResults(array $testArray, array &$errors)
{
if (!in_array(false, $testArray, true) || !in_array(null, $testArray, true)) {
foreach($testArray as $key => $value)
{
$errors[$key] = '';
}
return true;
}
if ($testArray['name'] !== true) { //You can make a function and do various test.
$errors['name'] = 'That is not a valid name.';
}
if ($testArray['clour'] !== true) { //You can make a function and do many test.
$errors['colour'] = 'That is not a valid colour.';
}
return false;
}
function processUserInput(array &$filteredData, array $filterRulesArray, array $validationRulesArray, array &$cleanData, array &$errors)
{
$filteredInput = null;
$tempData = sanitizeArray($filterRulesArray);
if (!$checkFilterResults($tempData, $errors)){
throw new UnexpectedValueException("An input value was unable to be sanitized.");
//Consider forcing the page to redraw.
}
$filteredData = $tempData;
$validatedData = validateArray($filteredData, $validationRulesArray);
if (!$checkFilterResults($validatedData, $errors)){
return false;
}
$errors['form'] = '';
$cleanData = $validatedData;
return true;
}
function htmlEscapeArray(array &$filteredData)
{
foreach($filteredData as $key => &$value)
{
$value = htmlspecialchars($value, ENT_QUOTES | ENT_HTML5, 'UTF-8', false);
}
return;
}
Basic Main Line
try {
$filterRulesArray = []; //You define this.
$filteredData = []; //A temporary array.
$validationRulesArray = []; //You define this.
$validatedData = null; //Another temporary array.
$results = null; //Input processing results: true or false.
$cleanData = null; //Filtered and validated input array.
$errors = []; //Any errors that have accumulated.
if (isset($_POST, $_POST['submit'], $_POST['colour']) && !empty($_POST)) {
$results = processUserInput($filteredData, $filterRulesArray, $validationRulesArray, $cleanData, $errors);
} else {
$errors['form'] = "You must fill out the form."
}
if ($results === true) {
$name = $cleanData['name']; //You can do what you want.
$colour = $cleanData['colour']; //You can do what you want.
//header("Location: http://url.com/registration/thankYou/")
//exit;
}
//Prepare user input for re-display in browser
htmlEscapeArray($filteredData);
} catch (Exception $e) {
header("Location: http://url.com/samePage/"); //Force a page reload.
}
Let the form redraw if input processing fails.
Use the $errors array to display error messages.
Use the $filteredData array to make the form sticky.
<html>
<head>
<title>Your Webpage</title>
</head>
<body>
<h1>My Form</h1>
<form action="/" method="post">
<!-- Make spots for error messages -->
<input type="text" name="name" placeholder="Acme Corp" value="PUT PHP HERE"/>
<!-- No time to display sticky radios! :-) -->
<input name="colour" type="radio" checked="checked" value="red">Red<br>
<input name="colour" type="radio" value="blue">Blue<br>
<input name="colour" type="radio" value="green">Green<br>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
Tip:
It may be better to submit numbers for radios, as opposed to longer string values like (red, green, blue). Numbers are easier to sanitize and validate. Naturally, then you must translate the input number into its corresponding string. You would do that after validation has finished, but before using the values. Good luck!
you can access this using array like this.
$data[] = $_POST['name'];
$data[] =$_POST['colour'];
Or combine both variable
$data = $_POST['name'].'&'.$_POST['colour'];
Use Array in php for this process as follows:
if (isset($_POST['submit'])) {
$array_val = array(
"name"=> $_POST['name'],
"color"=> $_POST['color']
);
}

PHP: Trying to upload multiple files, or a single file

protected function upload($name) {
$files = array();
// if block 1
if(!empty($_FILES[$name]['tmp_name'])) {
for($i = 0; $i < count($_FILES[$name]['tmp_name']); $i++) {
// if block #2
if(!empty($_FILES[$name]['tmp_name']) && is_uploaded_file($_FILES[$name]['tmp_name'][$i])) {
# we're dealing with multiple uploads
$handle['key'] = $name;
$handle['name'] = $_FILES[$name]['name'][$i];
$handle['size'] = $_FILES[$name]['size'][$i];
$handle['type'] = $_FILES[$name]['type'][$i];
$handle['tmp_name'] = $_FILES[$name]['tmp_name'][$i];
// put each array into the $files array
array_push($files,$this->_process_image($handle));
}
#block 3...
}
return $files;
}
return false;
}
I'm trying to create a function that will handle multiple upload scenarios: multiple file uploads per submit, and one file upload per submit, using a variety of file inputs.
The above method...
works as expected with two inputs
<input name="multiple[]" type="file">
<input name="multiple[]" type="file">
and a single input using multiple...
<input name="multiple[]" type="file" multiple>
but not a single input using a single upload
<input name="single" type="file">
Now, I noticed that if I change the name of single to single[] it works. So I copied block #2 and added it as another block (where #3 is), but this time without using [$i] and it worked for the single input, but failed if i had multiple inputs but only used one input to upload one file (not uploading 2 files using both inputs).
My brain hurts. How can I get this to work for all these scenarios?
Edit: When I say it's not working, I mean it's not even processing. No output, no errors, nothing. I think it's just being skipped over, which is why I added block #3...
HTML
<form action="file-upload.php" method="post" enctype="multipart/form-data">
Send these files:
<br />
<input name="userfile[]" type="file" />
<br />
<input name="userfile[]" type="file" />
<br />
<input type="submit" value="Send files" />
PHP(file-upload.php)
<?php
if ($_FILES['upload']) {
$file_ary = reArrayFiles($_FILES['userfile']);
foreach ($file_ary as $file) {
if(intval($file['error'])==4){
continue;
}
//If you upload a single file this will execute only once
print 'File Name: ' . $file['name'];
print 'File Type: ' . $file['type'];
print 'File Size: ' . $file['size'];
}
}
function reArrayFiles($file_post) {
$file_ary = array();
$file_count = count($file_post['name']);
$file_keys = array_keys($file_post);
for ($i=0; $i<$file_count; $i++) {
foreach ($file_keys as $key) {
$file_ary[$i][$key] = $file_post[$key][$i];
}
}
return $file_ary;
}
?>
Files Output :
Figured it out and it was really easy. I needed to check if the $_FILES array contained more than one file and process accordingly. probably a little bit more code than I'd like, but it's working exactly how I wanted.
protected function upload($name) {
$files = array();
if(!empty($_FILES[$name]['tmp_name'])) {
# *** THIS IF BLOCK SOLVED THE PROBLEM ***
# JUST CHECK IF $_FILES HAS MORE THAN ONE FILE
if(count($_FILES[$name]['tmp_name']) > 1) {
for($i = 0; $i < count($_FILES[$name]['tmp_name']); $i++) {
if(!empty($_FILES[$name]['tmp_name']) && is_uploaded_file($_FILES[$name]['tmp_name'][$i])) {
# we're dealing with multiple uploads
$handle['key'] = $name;
$handle['name'] = $_FILES[$name]['name'][$i];
$handle['size'] = $_FILES[$name]['size'][$i];
$handle['type'] = $_FILES[$name]['type'][$i];
$handle['tmp_name'] = $_FILES[$name]['tmp_name'][$i];
array_push($files,$this->_process_image($handle));
}
}
return $files;
} else {
if(!empty($_FILES[$name]['tmp_name']) && is_uploaded_file($_FILES[$name]['tmp_name'])) {
# we're handling a single upload
$handle['key'] = $name;
$handle['name'] = $_FILES[$name]['name'];
$handle['size'] = $_FILES[$name]['size'];
$handle['type'] = $_FILES[$name]['type'];
$handle['tmp_name'] = $_FILES[$name]['tmp_name'];
return $this->_process_image($handle);
}
}
}
return false;
}

PHP dynamic for loop validation

I am trying to validate this form dynamically using PHP so each file gets the same validation instead of only one file being validated. Below is my code to try and explain this better.
This is the for loop which outputs a number of <input type="file" /> fields to the user.
$items = sanitize($_GET['item']);
for($i=1; $i<=$items; $i++) {
echo $item = '<input type="file" name="photo'. $i .'" />';
}
This is the validation for one of these fields
$file_size = $_FILES['photo1']['size'];
if($file_size > 10485760) {
echo 'Photo 1 is too large. Maximium file size is 10MB.';
}
I am not sure how to accomplish this validation for every field in the for loop. This is what I have tried so far.
if($file_size.$i > 10485760) {
echo 'Photo '. $i .' is too large. Please choose a smaller file.';
}
This does not work though. Please can someone help me out with this?
Many thanks in advance, Harry
Array keys can be dynamic:
for ($i = 1; $i <= $some_limit; $i++) {
$size = $_FILES["photo{$i}"]['size'];
if ($size > ...) { etc... }
}
With your $size . $i, you'd be taking the size of the first file, e.g. 1024 bytes, and concatenating it with the $i value, e.g. 1024 . 2 and ending up with 10242.
Try something like:
foreach ($_FILES as $id => $details) {
$size = $details['size'];
# validate...
}
input name can be with square bracket. When form is submitted input fields can be accessed as array. such as:
html form:
<input type="file" name="photo[]">
<input type="file" name="photo[]">
<input type="file" name="photo[]">
php:
foreach($_FILES['photo'] as $key => $p) {
$file_size = $p['size'];
if($file_size > 10485760) {
echo "Photo $key is too large. Maximium file size is 10MB.";
}
}
This should work. Thank You.

Check/count if file array is empty in php

$_FILES array:
HTML:
<input type="file" name="smth[]" id="smth1" />
<input type="file" name="smth[]" id="smth1" />
<input type="file" name="smth[]" id="smth1" />
How can i check if file array is empty? (no files selected).
PHP:
if (CHECK) {
...operating with $_FILES...
}
Thank you for your answers.
function any_uploaded($name) {
foreach ($_FILES[$name]['error'] as $ferror) {
if ($ferror != UPLOAD_ERR_NO_FILE) {
return true;
}
}
return false;
}
if (any_uploaded('smth')) {
// ..operating with $_FILES...
}
something like
if(isset($_FILES) && count($_FILES) > 0){
...
?
Actually you'd need to iterate through your $_FILES and check for UPLOAD_ERR_NO_FILE in the error-key. See http://php.net/manual/en/features.file-upload.errors.php for more.
Apart from that, there are countless ways of checking if an array is empty! i.e. empty() or count()
just check for the file's name:
foreach($_FILES as $key => $val){
if(strlen($_FILES[$key]['name']) > 0){
//here we got a file from user
}else{
//no files received
}
}

Categories