PHP loop to make MYSQL Queries - php

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!

Related

Updating rows with 388 columns in a MySQL database

I have a problem with updating a table inside a MySQL database with about 388 columns. Inserting new rows works great, but updating existing ones doesn't (I do not get any error messages). I am also not very sure if the way I use to insert/udpate the
data is the very best as I do have a very long code, which is also very fragile for errors. Well, I am sure this could be solved a lot better!
Here is my code: https://codeshare.io/5DZODE
What if I use this code for every single of those 388 values?
insert into $table (field, value) values (:name, :value) on duplicate key update value=:value2
Help and ideas for improvement would be great! Thanks!
You could use the "REPLACE INTO" Statement instead of insert, that way you will only have to print the data once
eg
REPLACE INTO `values` (`id`,...) VALUES ($id,...)
Also to improve the php code(to make it more fail proof) I Would probably make an array containing all the variables and then print the SQL statement based on those values FX
$values = array('id'=> $id, ....);
$columns = array();
$replaceValues = array();
$insertValues = array();
foreach ($values as $key => $value)
{
$columns[] = "`$key`";
$replaceValues[] = ":$key";
$insertValues[":$key"] = $value;
}
$pdo = new PDO('mysql:host=xyz;dbname=xyz','xyz','xyz');
$statement = $pdo->prepare('REPLACE INTO `values` ('.implode(',',$columns).') VALUES ('.implode(',',$replaceValues).')');
$statement->execute($insertValues);

Looping an entire form into a MySQL db row?

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);

Assign POST values to an array in a loop and put array into a database

I have an array containing the names of form input names:
$minmax = array('bed_min', 'bed_max', 'rec_min', 'rec_max', 'bath_min', 'bath_max', 'value_min', 'value_max');
The names are identical to the corresponding columns in a database. Instead of using an sql query like so:
$bed_min=$_POST['bed_min'];
$bed_max=$_POST['bed_max'];
$rec_min=$_POST['rec_min'];
$rec_max=$_POST['rec_max'];
$bath_min=$_POST['bath_min'];
$bath_max=$_POST['bath_max'];
$value_min=$_POST['value_min'];
$value_max=$_POST['value_max'];
$query = "UPDATE first_page SET bed_min='$bed_min', bed_max='$bed_max', rec_min='$rec_min', rec_max='$rec_max', bath_min='$bath_min', bath_max='$bath_max', value_min='$value_min', value_max='$value_max', WHERE email_address='$email' ";
Is there a way to automate all this into a smaller lump of code? I know the POST values should not be added to the query diectly, so maybe a loop to assign the POST values to a corresponding array of variables using something like:
foreach ($minmax as $var){
$var = $_POST[$var]
}
(nb i dont think this snippet will work but ive added it because I think with a bit of editing it might!)
After the list of variables have been assigned the POST values, do the update in the $query using two arrays, one with the list of values and one with the list of database columns. Again I dont know how this will work, so pointers would be helpful!
You don't really need the $minmax array of form input names since you can get those from the keys of $_POST.
If the values are all numbers, like they seem to be, then you could do it all in one line like this:
$query = "UPDATE first_page SET " . vsprintf(implode("='%d', ", array_keys($sanitized_POST))."='%d'", array_values($sanitized_POST))." WHERE email_address='$email'";
That's assuming you have already sanitized the items from $_POST into a new array named $sanitized_POST. I know you said in the above comment to ignore sanitization, but I thought I'd add it so you know I'm not suggesting to use the values straight from $_POST.
You could sanitize the $_POST array with something like this:
$sanitized_POST = array_map(function($item) {
return mysqli::real_escape_string($item);
}, $_POST);
Honestly though, you should try to come up with a solution that uses prepared statements.
On a side note, if you have the sanitized post array, then this one line will essentially do what Quixrick has done with variable variables in one of the other answers:
extract($sanitized_POST);
If you assume that all of the values in post have the same names (array keys) as your columns, then something like this could work for you:
$query = "UPDATE first_page SET ";
foreach ($_POST as $key => $var){
$query .= " $key='$var',";
}
$query = rtrim($query,',') . " WHERE email_address='$email' ";
You probably want to use 'Variable Variables' here. Basically, you'd use a double dollar sign $$ to create a variable with the name of the array value.
$_POST['bed_min'] = 'Rick';
$minmax = array('bed_min', 'bed_max', 'rec_min', 'rec_max', 'bath_min', 'bath_max', 'value_min', 'value_max');
foreach ($minmax as $var){
$$var = $_POST[$var];
}
print "<BR>BED MIN: ".$bed_min;
This outputs:
BED MIN: Rick

Mysql query within for loop not inserting all values

I have the following for loops, which should insert values into a mysql table. There is a users array and it is looping over the array and calculation statistics, and it should be inserting all the values into the mysql table, but it only inserts the operation done on the first element of the users array and not the rest. It is ignoring the first for loop, and only inserts for the second for loop, even though, I can see that the loops are doing what they are supposed to do, it is just not being inserted into mysql.
for($i=0; $i<count($users); $i++)
{
for($j=$i+1; $j<count($users); $j++)
{
$user1=$users[$i];
$user2=$users[$j];
$dat1=getData($user1);
$dat2=getData($user2);
$union=count(array_unique(array_merge($dat1, $dat2)));
$intersect=count(array_intersect($dat1, $dat2));
$rate=$intersect/$union;
$sql = "INSERT IGNORE into dat_net VALUES ($user1,$user2,$union,$intersect,$rate)";
$sqlresults = mysql_query($sql);
echo " ".$user1." ".$user2." \n";
if ($sqlresults === false) {
// An error has occured...
echo mysql_error();
}
}
}
Solved due to tips in the comments: I had inadvertently set up keys for the columns, so it wasn't inserting due to duplication.
First of all insert all data using one query. Generate it in for loop and call mysql query once.
You can check if your generated query works simply by echo it before execute and try to run it using some sql client.
try this,
$sql = "INSERT IGNORE into dat_net VALUES ('{$user1}','{$user2}','{$union}','{$intersect}','{$rate}')";
But it will be good if you create a insert query in foreach loop and then fire it once after completing foreach loop.

Mysql insert using array

I have an array stored in a variable $contactid. I need to run this query to insert a row for each contact_id in the array. What is the best way to do this? Here is the query I need to run...
$contactid=$_POST['contact_id'];
$eventid=$_POST['event_id'];
$groupid=$_POST['group_id'];
mysql_query($query);
$query="INSERT INTO attendance (event_id,contact_id,group_id) VALUES ('$eventid','$contactid','$groupid')";
Use a foreach loop.
$query = "INSERT INTO attendance (event_id,contact_id,group_id) VALUES ";
foreach($contactid as $value)
{
$query .= "('{$eventid}','{$value}','{$groupid}'),";
}
mysql_query(substr($query, 0, -1));
The idea here is to concatenate your query string and only make 1 query to the database, each value-set is separated by a comma
Since no one hasn't stated that yet, you actually cannot do this:
$query = '
INSERT INTO [Table] ([Column List])
VALUES ([Value List 1]);
INSERT INTO [Table] ([Column List])
VALUES ([Value List 2]);
';
mysql_query($query);
as this has been prevented to prevent sql injections in the mysql_query code. You cannot have semicolon within the given query param with mysql_query. With the following exception, taken from the manual comments:
The documentation claims that "multiple queries are not supported".
However, multiple queries seem to be supported. You just have to pass
flag 65536 as mysql_connect's 5 parameter (client_flags). This value
is defined in /usr/include/mysql/mysql_com.h:
#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
Executed with multiple queries at once, the mysql_query function will
return a result only for the first query. The other queries will be
executed as well, but you won't have a result for them.
That is undocumented and unsupported behaviour, however, and easily opens your code to SQL injections. What you can do with mysql_query, instead, is
$query = '
INSERT INTO [Table] ([Column List])
VALUES ([Value List 1])
, ([Value List 2])
[...]
, ([Value List N])
';
mysql_query($query);
so you can actually insert multiple rows with a one query, and with one insert statement. In this answer there's a code example for it which doesn't concatenate to a string in a loop, which is better than what's suggested in this thread.
However, disregarding all the above, you're probably better of still to use a prepared statement, like
$stmt->prepare("INSERT INTO mytbl (fld1, fld2, fld3, fld4) VALUES(?, ?, ?, ?)");
foreach($myarray as $row)
{
$stmt->bind_param('idsb', $row['fld1'], $row['fld2'], $row['fld3'], $row['fld4']);
$stmt->execute();
}
$stmt->close();
Use something like the following. Please note that you shouldn't be using mysql_* functions anymore, and that your code is suseptible to injection.
for ($i = 0; $i < count($contactid); $i++) {
$query="INSERT INTO attendance (event_id,contact_id,group_id) VALUES ('$eventid','$contactid[$i]','$groupid')";
mysql_query($query);
}
I'm not sure running multiple queries is the best thing to do, so won't recommend making a for loop for example, that runs for each element of the array. I would rather say, make a recursive loop, that adds the new elements to a string, that then gets passed to the query. In case you can give us a short example of your DB structure and how you'd like it to look like (i.e. how the array should go into the table), I could give you an example loop syntax.
Cheers!
What about:
$contactIds = $_POST['contact_id'];
$eventIds = $_POST['event_id'];
$groupIds = $_POST['group_id'];
foreach($contactIds as $key => $value)
{
$currentContactId = $value;
$currentEventId = $eventIds[$key];
$currentGroupId = $groupIds[$key];
$query="INSERT INTO attendance (event_id,contact_id,group_id) VALUES ('$currentEventId','$currentContactId','$currentGroupId')";
mysql_query($query);
}
Well, you could refactor that to insert everything in a single query, but you got the idea.

Categories