Looping an entire form into a MySQL db row? - php

I'm hoping someone can give me a suggestion on a challenge I am facing. I am not sure that I'm able to do this the way I envision, so looking for advice from those more experienced.
I have a database table with around 20 columns. It's a lot of columns and unfortunately I cannot change that. The goal is to take a form submission and insert it into this table. So what I have is, the field names are identical to the column names in the database.
To try and keep the code cleaner, I would like to just pull the entire form (key and value) in, instead of doing the traditional $varWhatever = $_POST['whatever']; 20 times. Using something like this: foreach ($_POST as $key => $value)
Now my question is, if at all possible, how can I run that foreach loop in a way that will let me put the keys and values into a single SQL statement?
"INSERT INTO table_name (Loop all keys here) VALUES (Loop related values here)"
Is this even possible, or should I just go back to the more traditional way I mentioned above?
One way I am thinking is, before starting the loop, I could create the empty row and grab it's ID, then within the loop, I could run an update query on the row matching the ID. Sounds sloppy though.

Here is a solution I came up with. You first have to define an array of field names that acts as a whitelist of expected inputs. Then you just loop through that array to build a parameters array to bind the submitted values. And implode the array with a comma when building the query.
$fields = array('field1','field2','field3');
$binds = array();
foreach ($fields as $field) {
$binds[":$field"] = $_POST[$field];
}
$sql = "INSERT INTO table_name (" . implode(',',$fields) . ") VALUES (" . implode(',',array_keys($binds)) . ")";
$db->prepare($sql);
$db->execute($binds);
This assumes you are using PDO.

Yes, you can loop for all keys (eg. do an array_keys), but I don't recommend blindly taking any submission parameter and putting it into a SQL query.
Instead, I would keep a list of all valid columns of the form and work with that, remembering that each value needs sanitization, too.
For example:
<?php
$columns = array('column1', 'column2', 'column3', …);
foreach ($columns as $column) {
if (!isset($_POST[$column])) {
die("No data for column $column\n");
}
}
if (!check_csrf($_POST['csrt_token'])) { … }
# (setup database connection)
$SQL = "INSERT INTO table_name (" . implode(", ", $columns) . ") VALUES (";
foreach ($column as $column) {
$SQL .= "'" . $mysqli->real_escape_string($_POST[$column]) . "',";
}
$SQL[strlen($SQL)-1] = ')';
$mysqli->query($SQL);

Related

How to fetch data using loop PHP statement from mysql to ios?

My system is composed of 3 components.
ios - php - mysql
If ios users select multiple 'id's,
then, ios app posts these selected 'id' request to server,
and, the server finds the data based on selected 'id's in MySQL.
and finally, the server passes these data to ios app.
These are the PHP statements I tried.
<?php
$id_0 = $_POST['0'];
$id_1 = $_POST['1'];
$id_2 = $_POST['2'];
$id_3 = $_POST['3'];
...
$id_n = $_POST['n'];
$conn = mysqli_connect('address', 'user', 'password', 'database');
$sql = "SELECT * FROM firstname WHERE id = '$id_0'";
if ($result = mysqli_query($conn, $sql)) {
$resultArray = array();
$tempArray = array();
while($row = $result->fetch_object()) {
$tempArray = $row;
array_push($resultArray, $tempArray);
}
} else {
}
mysqli_close($conn);
?>
To get multiple 'id' data, I found that I need to use loop statement.
But the problem is, the number of selected id are variable.
I think that in this code, I need two loop statement.
To get multiple data based on multiple id(the number of id are variable)
To append these data into array
I don't know how to use loop statement when the range is not defined.
How can I use loop statement in PHP, and how can I rearrange these codes?
I'm sure this question is a duplicate but I can't find an exact source.
Your current method means you need to run a whole MySQL query for each iteration.
As the query results will never change what the iteration contains, therefore; you can simply rework it to use MySQL IN to load all of your variables at once:
Step 1) Take all the values and place them in a single array.
$new = []; //new array
foreach ($_POST as $key=>$id){
// Check it is a numeric key
// Check id value is valid to avoid importing other POST values
if((int)$key == $key && (int)$id == $id){
$new[] = $id;
}
}
The above code block is nessecary to stop using values from $_POST['button'] or other posted data that should not be included. This step can be removed if you can clarify your posted data, such as saving all ids to a $_POST['id'] array itself.
Step 2) Empty the array of null/void or repeated values.
$new = array_unique($new);
Step 3) Turn the array into a string, inside the SQL
$arrayString = implode(',',$new);
Step 4) Plug the string into the SQL IN clause:
$sql = "SELECT * FROM firstname WHERE id IN (" . $arrayString . ") ORDER BY id";
Simplified and reduced:
$new = []; //new array
foreach ($_POST as $key=>$id){
if((int)$key == $key && (int)$id == $id){
$new[] = $id;
}
}
$new = array_unique($new);
$sql = "SELECT * FROM firstname WHERE id IN (" .
implode(',',$new) . ") ORDER BY id";
The SQL query above will give you an array of arrays, each one a different row. You can the order them, sort them and output them in PHP as you wish.
See also: This Q&A.
BUT
As expressed by others, you really, REALLY should be using Prepared Statements with MySQLi.
See also here, here and here to see further how to do it and WHY you should do it.
Top Tips:
Numerical columns (typical of id columns) in MySQL do not need the ' quotes.
Until you're using Prepared Statements you can typecast the variables to integers ((int)$var) to limit risk.
It is better to specify the columns you need rather than to use the * catch-all.
Your $_POST data should be an array $_POST['ids'][...].
Eat five different pieces of fruit or veg' a day.
Never trust user input!

Adding multiple fields separated by comma into database PHP

Thank you in advance for any help given! I'm very new to PHP and would love some advice/help! i want many id fields separated by comma to be inputted into a database separately with the same resource id variable.
Find a link to a picture here! Here, a user enters many ids for the name, and only one ID for the resource, I would like all ids to be entered into the database with the same resource id beside it
//so this is creating the array to split up the ids
$array = explode(",", $id);
//finding length of array
$length = count($array);
//now we want to loop through this array, and pass in each variable to the db
for ($x = 0; $x < $length; $x++) {
$sqlinsert= "INSERT INTO ids_to_resources (id, resource_id)
VALUES ($id [$x], $resource_id)"
$result = mysqli_query($dbcon,$sqlinsert);
}
I think it could be something like this code above but it doesnt seem to be working for me...
In short i want a user to enter many ID fields and only one resource field, and for this to be inputed into the database separately. I hope this makes sense!
Thanks again for any help given!
To only answer your question and not questioning your database schema. Have a look at the following code:
$ids = explode(",", $id);
$inserts = array();
foreach ($ids as $id) {
$inserts[] = "($id,$resource_id)";
}
$query = "INSERT INTO ids_to_resources (id,resource_id) VALUES " . implode(',', $inserts) . ";";
You can insert multiple rows in one sql query by seperating them with a comma. The code should generate a query like this:
INSERT INTO ids_to_resources (id,resource_id) VALUES (1,4),(2,4),(3,4);
You would be better off creating a separate table which has a new row for each record... the columns would be ID, NINJA_ID, RESOURCE_ID. Then insert it that way. Put an Index on RESOURCE_ID. This way you can easily search through the database for specific records, updating and deleting would be a lot easier as well.
But if you insist on doing commas,
$comma_ids = implode("," $array);
You don't have semicolon after this line and you musnt't have a space between $id and [$x]
$sqlinsert= "INSERT INTO ids_to_resources (id, resource_id)
VALUES ($id[$x], $resource_id)";

Create a query with a number of columns and tables variable

I have a database containing a number of tables. I also have a web-based application that is connected to it. For now I am using prepared queries.
I am trying to create a general query that will be able to take a variable number of input columns from different tables. (Basically the user checks boxes that create php variables that I need to pass to the query).
If I know that there will be let say 2 columns needed, it's easy, I only need to do something like,
SELECT $col1, $col2 FROM $table1 INNER JOIN $table2;
How can I change that so that any number of variables can be input in the query?
Thanks in advance,
Zohm
EDIT: I think I could maybe do an if/else condition in PHP or a switch and each case would correspond to a number of input columns, and each case would have its query. But this would do a lot of cases (the user could click 10 boxes for example) and It does not really seems right to do that. Moreover in the future if I need more cases I will have to change the code, which I rather not have to do.
i assume your form elements names are the table fields you are looking for. if this is the case you can loop through the post to build your fields table. Im not sure how you are setting a variable to have 2 values...
$_POST['field1'] = "true";
$_POST['field2'] = "true";
$_POST['field3'] = "false";
$_POST['field4'] = "true";
$fields = "";
foreach ($_POST as $key => $value)
{
$fields .= $key . ",";
}
which will end up with
$fields = "field1,field2,field4,";
now you have to remove that last comma,
$fields = substr($fields,0,-1);
so then you can:
$query = "SELECT " . $fields . " from table1...and so on.

SQL statement inside loop with PHP, good idea?

I ran into the following question while writing a PHP script. I need to store the first two integers from an array of variable lenght into a database table, remove them and repeat this until the array is empty. I could do it with a while loop, but I read that you should avoid writing SQL statements inside a loop because of the performance hit.
A simpliefied example:
while(count($array) > 0){
if ($sql = $db_connect->prepare("INSERT INTO table (number1, number2) VALUES (?,?)")){
$sql->bind_param('ii',$array[0],$array[1]);
$sql->execute();
$sql->close();
}
array_shift($array);
array_shift($array);
}
Is this the best way, and if not, what's a better approach?
You can do something like this, which is way faster aswell:
Psuedo code:
$stack = array();
while(count($array) > 0){
array_push($stack, "(" . $array[0] . ", " . $array[1] . ")");
array_shift($array);
array_shift($array);
}
if ($sql = $db_connect->prepare("INSERT INTO table (number1, number2)
VALUES " . implode(',', $stack))){
$sql->execute();
$sql->close();
}
The only issue here is that it's not a "MySQL Safe" insert, you will need to fix that!
This will generate and Array that holds the values. Within 1 query it will insert all values at once, where you need less MySQL time.
Whether you run them one by one or in an array, an INSERT statement is not going to make a noticeable performance hit, from my experience.
The database connection is only opened once, so it is not a huge issue. I guess if you are doing some insane amount of queries, it could be.
I think as long as your loop condition is safe ( will break in time ) and you got something from it .. it's ok
You would be better off writing a bulk insert statement, less hits on mysql
$sql = "INSERT INTO table(number1, number2) VALUES";
$params = array();
foreach( $array as $item ) {
$sql .= "(?,?),\n";
$params[] = $item;
}
$sql = rtrim( $sql, ",\n" ) . ';';
$sql = $db_connect->prepare( $sql );
foreach( $params as $param ) {
$sql->bind_param( 'ii', $param[ 0 ], $param[ 1 ] );
}
$sql->execute();
$sql->close();
In ColdFusion you can put your loop inside the query instead of the other way around. I'm not a php programmer but my general belief is that most things that can be done in language a can also be done in language b. This code shows the concept. You should be able to figure out a php version.
<cfquery>
insert into mytable
(field1, field2)
select null, null
from SomeSmallTable
where 1=2
<cfloop from="1' to="#arrayLen(myArray)#" index="i">
select <cfqueryparam value="myArray[i][1]
, <cfqueryparam value="myArray[i][]
from SomeSmallTable
</cfloop>
</cfquery>
When I've looked at this approach myself, I've found it to be faster than query inside loop with oracle and sql server. I found it to be slower with redbrick.
There is a limitation with this approach. Sql server has a maximum number of parameters it will accept and a maximum query length. Other db engines might as well, I've just not discovered them yet.

PHP loop to make MYSQL Queries

I have a list of IDs generated from a set of checkboxes as follows:
$list = mysql_real_escape_string(implode(',',$_POST['checkbox']));
which outputs a list like this:
a,b,c
I want to set a column in a MYSQL database that corresponds to each list item, I am unsuccessfully trying to create a query with a foreach loop like so:
$update_query= '';
foreach($list as $item){ //error on this line
$update_query .= "
INSERT INTO t (Col_1, Col_2)
VALUES ('".$item."',now());
";}
It fails telling me I have supplied an invalid argument for foreach(), but I'm not sure, a. what that means, and b. how to fix it; can anyone offer any guidance to get my loop working or a better way of doing this INSERT.
Thanks
$list is a string, not an array. Try passing in the array before you have imploaded it:
$update_query= '';
foreach($_POST['checkbox'] as $item)
{
$update_query .= "INSERT INTO t (Col_1, Col_2) VALUES ('".addslashes($item)."', now());";
}
You'd be much better off using prepared statements, though!

Categories