How handle multiple inputs from one form in PHP - php

I'm not sure how to ask this question. It procedural question I believe.
<input type="hidden" name="1[]" value="dummy">
<input type="radio" name="1[]" value="5">
<label> Very Good </label>
<input type="radio" name="1[]" value="4">
<label> Good </label>
<input type="text" name="1[]" size="20">
<br>
<input type="hidden" name="2[]" value="dummy">
<input type="radio" name="2[]" value="5">
<label> Very Good </label>
<input type="radio" name="2[]" value="4">
<label> Good </label>
<input type="text" name="2[]" size="20">
$_POST output:
[1] => Array
(
[0] => Text misc
)
[2] => Array
(
[0] => 5
[1] =>
)
From this I construct and INSERT statement.
INSERT INTO coached_tracked (coached_id, value, note)
VALUES ($key, $value[0], $value[1]);
This is are dynamically generated form inputs. A radio button, text field pair.
How can I handle an occurrence where the radio is not selected and the text field has value, like in the first instance. I want the option of having nothing selected so a default value seems not called for. I tried with both with and without a dummy value (I saw an example suggesting a hidden field as a possible solution.)
Suggestions.

You should not tell the database what ID to use. Let the database itself determine that by using an auto-incremented column.
First, start with a logical input name. Using just numbers is extremely confusing and looking at your code, I have absolutely no idea what you're doing. We also want everything to go into the same PHP $_POST variable to not have to iterate over all possible number cominations. That means we can just iterate over the one single array.
Let's say you're adding a coach to a database, so logically we would start with:
<input name="coach">
Now when we want to add multiple coaches instead of just one, we can use HTML array names, however I would recommend you hard-code them instead of auto-incrementing in your HTML, which should simplify things later on. We also pluralize it to coaches:
<?php
for ($i=0;$i<10;$i++) {
?>
<input name="coaches[<?=$i?>]">
<?php
}
Now if each coach contains a certain properties, let's say name, salary, note, etc, we can add the properties to the input names like so:
<?php
for ($i=0;$i<10;$i++) {
?>
<input name="coaches[<?=$i?>][name]">
<input name="coaches[<?=$i?>][salary]">
<input name="coaches[<?=$i?>][note]">
<?php
}
Then in PHP you just iterate over $_POST['coaches'] and then use the properties for each coach how you wish:
if (isset($_POST['coaches'])) {
foreach ($_POST['coaches'] as $coach) {
$name = $coach['name'];
$salary = $coach['salary'];
$note = $coach['note'];
// Now execute the query:
// INSERT INTO coached_tracked (name, salary, note)
// VALUES ($name, $salary, $note);
}
}
Note: remember to sanitize any user-supplied data by using prepared statements with bound parameters to make sure you're not open to SQL injection attacks.

Related

How to insert form values, some with same name, to multiple MySQL rows

I have been searching this for the last couple of hours and there are a few very similar questions and answers but none are quite working for my situation. What I'm trying to do is insert a list of songs set to the same value for two columns, one per row, and with a couple of options set via radio buttons. The latter is the reason why I can't just write all of the songs in a textarea and split them.
This is what the form looks like (obviously not fully designed)
There are only three there now while I get it working, in reality an unlimited amount may be added via javascript.
And the code:
<form action="" method="post">
<label>Session ID</label>
<input type="text" name="session-id"><br>
<label>Songs</label><br>
<input type="text" name="song-key[]"><input type="checkbox" name="is-partial[]"><input type="checkbox" name="is-jam[]"><br>
<input type="text" name="song-key[]"><input type="checkbox" name="is-partial[]"><input type="checkbox" name="is-jam[]"><br>
<input type="text" name="song-key[]"><input type="checkbox" name="is-partial[]"><input type="checkbox" name="is-jam[]"><br>
<input type="text" name="update-date" value="<?php echo date(" Y-m-d H:i:s ");?>" hidden readonly><br>
<input type="submit" name="submit" value="Submit">
</form>
The desired result, assuming the ID has been set and a unique song entered for each of the them, and whatever variety on the radio buttons, would be three table rows. session-id and update-date would all be the same value, the rest would be unique based on entry.
This is what I currently have, but it only inserts the last of the three songs.
for ($i=0; $i < count($_POST['song-key']); $i++ ) {
$sessionkey = mysqli_real_escape_string($connection, $_POST["session-key"]);
$songkey = mysqli_real_escape_string($connection, $_POST["song-key"][$i]);
$partial = mysqli_real_escape_string($connection, isset($_POST['is-partial'][$i])) ? 1 : 0;
$jam = mysqli_real_escape_string($connection, isset($_POST['is-jam'][$i])) ? 1 : 0;
$updated = mysqli_real_escape_string($connection, $_POST["update-date"]);
$sql = "INSERT INTO session_songs (session_key, song_key, is_partial, is_jam, last_updated)
VALUES ('$sessionkey', '$songkey', '$partial', '$jam', '$updated')";
}
What do I need to change to ensure all three (or more) are entered?
If you alter your input names, you can get a more useful $_POST array.
<input type="text" name="songs[0][key]">
<input type="checkbox" name="songs[0][is-partial]">
<input type="checkbox" name="songs[0][is-jam]"><br>
<input type="text" name="songs[1][key]">
<input type="checkbox" name="songs[1][is-partial]">
<input type="checkbox" name="songs[1][is-jam]"><br>
<input type="text" name="songs[2][key]">
<input type="checkbox" name="songs[2][is-partial]">
<input type="checkbox" name="songs[2][is-jam]"><br>
With specified keys, the checkbox type inputs will match up properly with the text inputs, where they way you have it now, they will not*, because only checked checkboxes are submitted to PHP. (Try only checking "is-partial" in the second and "is-jam" in the third row, and then var_dump($_POST), and you'll see that they both have index 0.)
If your form is structured like that, you can insert your records using a foreach loop instead of a for loop.
foreach ($_POST['songs'] as $song) {
$key = $song['key'];
$partial = isset($song['is-partial']) ? 1 : 0;
$jam = isset($song['is-jam']) ? 1 : 0;
// do the insert inside the loop rather than just building the SQL
}
The reason you're currently only getting the last one is that you're defining the SQL string inside the loop, but without executing the statement in the loop, you'll only get the values from the last iteration of the loop. Move your query execution inside the loop and you should get all three rows.
*unless they are all checked

Looping through multiple POST elements

I am trying to figure out how to loop through multiple POST form data that is dynamically pulled from a database and re-submit the modified data to a different table. For some reason (probably old age) I can't seem to come up with a solution that works.
I am already looping out all the records from one table (call it roster) and need to submit it to another table (call it roster2). The form is something similar to this:
<form name="name" action="form.php" method="post">
<input type="text" name="name1" value="15">
<input type="text" name="attended" value="1">
<input type="checkbox" name="nameid_12" value="12">
<input type="text" name="name2" value="8">
<input type="text" name="attended" value="1">
<input type="checkbox" name="nameid_6" value="6">
</form>
The 'name' and 'nameid' fields will always change and the number of records displayed will always be different (one day it could be 5 and the next 100).
What is the best way to loop through the POST data to submit it to the database keeping all the associations intact?
I am relatively new to working with PHP and I can't seem to figure out a good way to do this.
If you're going to generate them dynamically, I would recommend using PHP to place the ID of each form in the inputs on that form. So your original form would end up with these names:
<input type="text" name="name[12]" value="15">
<input type="text" name="attended[12]" value="1">
<input type="checkbox" name="nameid[12]" value="12">
<input type="text" name="name[6]" value="8">
<input type="text" name="attended[6]" value="1">
<input type="checkbox" name="nameid[6]" value="6">
Then your arrays will have keys corresponding to their form's ID. The array structure looks like this.
Array (
[name] => Array ( [12] => 15, [6] => 8 )
[attended] => Array ( [12] => 1, [6] => 1 )
[nameid] => Array ( [12] => 12 [6] => 6 )
)
Now we need to figure out which ids are actually present today. The array_keys() function generates an array of keys from any source array. Keys will be the same for each of the three elements, so I arbitrarily take the keys from [name].
$id_array = array_keys($_POST['name']);
Then, to access each element of the POST array, we'll use a foreach.
foreach ($id_array as $id) {
//assign variables
$name = $_POST['name'][$id];
$attended = $_POST['attended'][$id];
$nameid = $_POST['nameid'][$id];
//store
//Using whichever database style you like. I prefer PDO.
}
You can loop through the fields and retain their keys like so:
foreach ($_POST as $field_name => $field_value) {
// Storage
}

Iterating through set $_POST variables by type?

I have user inputs as follows:
<form action="special.php" method="post">
<input name="first1"> <input name="last1"> <input name="age1">
<input name="first2"> <input name="last2"> <input name="age2">
<input name="first3"> <input name="last3"> <input name="age3">
<input name="first4"> <input name="last4"> <input name="age4">
<input name="first5"> <input name="last5"> <input name="age5">
<input name="first6"> <input name="last6"> <input name="age6">
...
N
</form>
The amount of user inputs in the form is determined by the user; meaning, the user can add 5,10,20 additional lines to the code above, creating new input elements (following the pattern above) as they fit.
My question is, once the form gets submitted, what is an easy way to iterate and print out all the SET POST variables?
Something like:
for($i=0; $i < $numPostVars; $i++){
if(isset($_POST['first".$i."'])){
//echo all first names post variables that are set
}
}
// do the same from last names & age in separate loops
I think the trick is to name your variables slightly different, and take advantage of PHP's feature which will unpack them as arrays for you. Just use the syntax: first[1]. Then in PHP, $_POST['first']['1'] is where you will find it. You can then iterate all your "first" inputs with
foreach($_POST['first'] as $first_input) {
// ...
}
Also keep in mind that browsers may not send the field if it is empty when the user submits.
Here is what the inputs should look like in HTML:
<input name="first[1]"> <input name="last[1]"> <input name="age[1]">
As noted by user #DaveRandom, consider also a more hierarchical structure (think "rows" like from your db):
<input name="people[1][first]"> <input name="people[1][last]"> <input name="people[1][age]">
Inputs can be treated as arrays with a syntax very similar to that used in PHP:
<input name="name[1]" value="value 1">
<input name="name[2]" value="value 2">
This would result in a $_POST['name'] that looks like this:
array(
1 => "value 1",
2 => "value 2"
);
This principle can be expanded to incorporate multi-dimensional and associative arrays. So if you were to name your inputs like this:
<input name="rows[1][first]"> <input name="rows[1][last]"> <input name="rows[1][age]">
<input name="rows[2][first]"> <input name="rows[2][last]"> <input name="rows[2][age]">
...you would be able to easily iterate over $_POST['rows'] with a foreach construct. The data structure will be very similar to a set of database results.
foreach ($_POST['rows'] as $row) {
// do stuff with $row['first'], $row['last'] and $row['age'] here
}
A couple of things to note:
Unlike PHP, associative array keys in HTML do not require quotes, and using them will produce a result you may not expect. It will work, but not in the way you might think. You still need to use quotes in PHP though.
As far as I am aware, this syntax is not a W3C standard. PHP, however, always handles it as expected.

how to update sql table with a variable number of fields in the form php

I have a variable number of fields in a form.
The number of text fields are defined by the user with a function in jquery, but the final code of the form (example) is this:
<form id='form_educ' name='form_educ' method='post' action='form/educ.php'>
<div id='educ'>
<input type='text' name='date1' id='date1'/>
<input type='text' name='date2' id='date2'/>
<input type='text' name='date3' id='date3'/>
<input type='text' name='date4' id='date4'/>
....
</div>
<input type='submit' name='form_educ' value='Refresh'/>
</form>
These text fields when added by the user is create a sql INSERT TO (in another file):
$date = clean($_GET['date']);
"INSERT INTO educ (index_of_form, date, email) VALUES('$index', '', '" .mysql_real_escape_string($_SESSION['SESS_EMAIL']). "')";
$date is date1, or date2, or date3 or date4 (example).
Now in the file educ.php I want to update all text fields in the mysql database.
Usually it is a
$example = clean($ _POST ['example']);
I can do an update in the table and is resolved.
But in my case how can I get all the values โ€‹โ€‹of the text field on the form and set the $_POST var if the number of fields is variable (could be date1, date2, date3, date4)?
I can think of no reason why form field name should be a unknown variable. Unless you're dealing with repeatable fields, in which case you would use an array like dates[], and you'd know what to expect in the process script.
For additional info see for example: http://www.web-design-talk.co.uk/58/adding-unlimited-form-fields-with-jquery-mysql/
Word of warning for future. When you make the field repeatable, allow users also to delete the fields they might have accidentally insertet. Watch out in the process script missing array keys (numerical index from 0โ€“10 might be missing some values if the user deleted some form fields before submitting). You can reset the array keys with the array_merge function. Missing keys is an issue if you have two arrays you are trying to add into database as syncronized.
Updated to answer the comment.
Sorry, I don't undestand your question. You don't necessarily have to use hidden field. What you need is a database structure to match your forms function: to support one to many relationship. After all you are inserting multiple dates that relate to one person, or some specific event type, or what ever. Lets assume one user wants to add his three favorite dates in the world. Your form's source code looks like:
<input type="text" name='dateLover' id='dateLover'/>
<input type="text" name="dates[]" id="date1" /> //you need a increasing variable for these id numbers (or dont't put the id at all)
<input type="text" name="dates[]" id="date2" />
<input type="text" name="dates[]" id="date3" />
In addition you could have more fields such as <input type="text" name="extra" />. In submitted $_POST array there would be variables and arrays like: $_POST['dateLover'], $_POST['date'][0], $_POST['date'][1], $_POST['date'][2], $_POST['extra']. You'd take the non-repeatable values straight out of the $_POST array but you need a foreach (or some else loop) to handle the dates array.
Your database has to contain two tables (structure simplified):
person: id, dateLover
date: id, dateLover FK to person.dateLover, date
In your process script you have to:
insert a new dateLover to person and use last_insert_id to get his id
use a foreach to insert new dates to table date (with a dateLover's id as FK)
This all is pretty well demonstrated in the link I supplied earlier. For now, it's hard to give an complete example without undestanding the actual problem.
Update 2.
You are serializing the form, not the div's. So your (dynamically generated) could look like this:
<form id="form_educ" name="form_educ" method="post" action="form/educ.php">
<div id="educ">
<div><!--This is for layout only-->
<input type="text" name="dates[]" id="date0" />
<input type="text" name="names[]" id="name0" />
</div>
<div>
<input type="text" name="dates[]" id="date1" />
<input type="text" name="names[]" id="name1" />
</div>
<div>
<input type="text" name="dates[]" id="date2" />
<input type="text" name="names[]" id="name2" />
</div>
</div>
<input type="submit" name="form_educ" value="Refresh" />
</form>โ€‹
And in your process file you take these arrays from $_POST array and insert them into database maybe like this (with properly escaped and checked values of course...):
//dynamic part of the query
$qEnd = '';
$i = -1;
//this is static part of the query
$qBeginning = "INSERT INTO `date` (`id`, `date`, `name`) VALUES ";
foreach ($_POST['dates'] as $key => $date){
$i++;
$qValues[$i] = "(null, '{$date}', '{$_POST[names][$i]}')"; //never do this, always check values...
//value sets are concatenated one after another to the $qEnd
$qEnd .= $qValues . ',';
}
//combine the query parts and remove extra "," from the end
$q = $qBeginning . rtrim($qEnd, ',');
//now the (single) query ($q) is ready to be executed, echo it just for the fun of it
id should be auto increment field, or this kind of stuff doesn't work on the fly.
Again, this all should be clear in the jQuery link example so please read it carefully.
You should know all of the possible columns that could be updated before hand. Just check to see if those are set in the $_POST variable, then if they are append the insert or update statement with those values.
DANGER: Just looping on the $_POST variable looking at all params may end up inserting not database related POST fields into your insert statement and breaking.
Also when using these methods, be aware of SQL Injection, and use parameterized queries and never directly insert POST variable names or values into the SQL Statment.

How to validate multi-checkbox state?

I am using position absolute's validation engine for my form. I would like to check whether at least one checkbox from group is selected. In examples it is done by setting the same name attribute for group of checkboxes.
I cannot name checkboxes with the same name, because I am saving their state in database with following code:
$values = array(
'checkbox1' => null,
'checkbox2' => null
);
foreach (array_intersect_key($_POST, $values) as $key => $value) {
$values[$key] = mysql_real_escape_string($value);
}
$query_add_candidate=sprintf("INSERT INTO dbase (checkbox1, checkbox2) VALUES ('$values[checkbox1]', '$dates[checkbox2]')"
Now checkbox1 and checkbox2 are validated individually, beacuse they have different names. How can I check if selected is at least one of them?
Here is my HTML code:
<input class="validate[minCheckbox[1]] checkbox" type="checkbox" name="checkbox1" id="maxcheck1" value="1"/> Text1
<input class="validate[minCheckbox[1]] checkbox" type="checkbox" name="checkbox2" id="maxcheck2" value="2"/> Text2
on php ,
if(!$_POST['checkbox1'] && !$_POST['checkbox2']){
echo 'Error check at least one';
}
but what you really want is an array,
HTML,
<input type="checkbox" value="ch1" name="check[]" />
<input type="checkbox" value="ch2" name="check[]" />
php
<?php
if(empty($_POST['check'])){
echo 'Error: hey, check at least one will you!?';
}
?>
so this way you don't have to check all of them one by one, especially if you have loads of them on the same page.
NOTICE: You should also know, if checkbox is not ticked it will also not be set on the php $_POST superglobal, otherwise if it is ticked, it will show whatever the value="..." holds,
if its posted then its checked,
so if you have it in $_POST["checkbox_name"] then its checked, otherwise it wont be posted.
You can either add loads of code to reimplement control arrays in a poor way, or you can alter the code that builds your query so it can accept control arrays.
I would prefer the latter.

Categories