Passing an array via POST in PHP to be inserted into MySQL - php

I have a form that allows users to input classes and activities into multiple fields, these fields are declared like this :
label for ="classact">Classes and Activities</label>
<input type = "text" name = "classact[0]" value ="" id ="classact[0]">
<input type = "text" name = "classact[1]" value ="" id ="classact[1]">
<input type = "text" name = "classact[2]" value ="" id ="classact[2]">
When the form is passed this is the code that handles in the insert:
$maininsert = "INSERT INTO `camptest`
(`name`, `city`, `phone`, `photo`)
VALUES
('$_POST[name]', '$_POST[city]', '$_POST[phone]', '$photoinfo')
SET #lid = LAST_INSERT_ID()
";
$classactinsert = "INSERT INTO `class_act`
(`cid`";
for($i = 0; $i < 3; $i++)
{
if(isset($_POST['classact'][$i]))
{
$temp = $i+1;
$classactinsert = $classactinsert . ",`act$temp`";
}
}
$classactinsert = $classactinsert . ")
VALUES
('#lid'";
for($i = 0; $i < 3; $i++)
{
if(isset($_POST['classact'][$i]))
{
$classactinsert = $classactinsert . ",'$_POST[classact][$i]";
}
}
$classactinsert = $classactinsert . ")";
$indata = $maininsert . $classactinsert;
$result = mysql_query($indata);
I realize thats alot of code, but upon filling out the form and submitting this is the query that gets generated:
INSERT INTO `camptest` (`name`, `city`, `phone`, `photo`) VALUES ('Multiple Activities', 'Nowhere', '555-555-1111', 'images/51127f6b06d1e.jpg') SET #lid = LAST_INSERT_ID() INSERT INTO `class_act` (`cid`,`act1`,`act2`,`act3`) VALUES ('#lid','Array[0],'Array[1],'Array[2])
The query is not inserting, but its not throwing back any errors either, even though I have them turned on.
My main question is, what am I doing wrong that is causing the values to act1, act2, and act3 to show up as Array[0], Array[1], and Array[2]?
My secondary question is, am I even going about this the right way? I'm a little new to php and I'm afraid I might be doing this the hard way?
Any help would be appreciated, let me know if you need any additional information.

It does not insert anything, because (among other things) your query string is not being built correctly.
('#lid','Array[0],'Array[1],'Array[2])
The apostrophes are messed up. I'd like to suggest a (in my opinion) cleaner and more structured way to perform your task:
Note: You are obviously working with the mysql_*-stack, so my example is also based on it. But be aware that this is deprecated. Please use mysqli or even better: PDO instead.
<?php
$maininsert = "INSERT INTO `camptest`
(`name`, `city`, `phone`, `photo`)
VALUES
('{$_POST['name']}', '{$_POST['city']}', '{$_POST['phone']}', '$photoinfo')";
//perform the main insert and fetch the insert id
mysql_query($maininsert);
$last_id = mysql_insert_id();
// Put the keys and values of the acts in arrays. We can already
// populate them with the one key-value-pair we already know
$act_keys = array('cid');
$act_values = array($last_id);
foreach($_POST['classact'] as $key => $value) {
//walk through the POSTed acts and add them to the corresponding array
$act_keys[] = 'act'.($key+1);
$act_values[] = $value;
}
//Now build the whole string:
$insert_acts = "INSERT INTO `class_act`
(`" . implode("`, `", $act_keys) . "`)
VALUES
('" . implode("', '", $act_values) . "')";
//and finally perform the query:
mysql_query($insert_acts);
Please also note that this code is highly vulnerable concerning SQL-Injection and should absolutely not be used in production!!! Make sure to either use prepared statements (like with PDO) or/and to sanitize your input properly.
Also, this solution is just my suggestion and one of many ways to do it. But hey, you asked for an opinion :) PHP is very flexible language, so it's easy to get stuff done, but there are many ways to get it done, so there are always chances to pick a hard an ugly one. Other, especially strong typed languages might prevent that by design. But PHP is really easy to learn and I'm sure your code will improve gradually :)
Another thing I've noticed: You don't need to specify the array-keys in your HTML, you just need to make clear that it's an array with [] behind the name. Also, I'm not sure if the id-attributes you using are valid, but you might want use something more simple:
<input type="text" name="classact[]" value="" id="classact1">
<input type="text" name="classact[]" value="" id="classact2">
<input type="text" name="classact[]" value="" id="classact3">
In the next step, you might want to refactor your code a little to make it even more structured and readable. Since you are performing one task, which is 'inserting something into a table', twice, we could also make a resusable function out of it:
<?php
function my_insert($table, $data) {
// We leverage the flexibility of associative arrays
$keys = "`" . implode("`, `", array_keys($data)) . "`";
$values = "'" . implode("', '", $data) . "'";
mysql_query("INSERT INTO `{$table}` ({$keys}) VALUES ({$values})");
return mysql_insert_id(); //This might come in handy...
}
//in order to use this function, we now put our data into associative arrays:
$class_insert = array(
'name' => $_POST['name'],
'city' => $_POST['city'],
'phone' => $_POST['phone'],
'photo' => $photoinfo
);
$class_insert_id = my_insert('camptest', $class_insert); //and pass it to the function
// You can either build the array while looping through the POSTed values like above,
// or you can pass them in directly, if you know that there will always be 3 values:
$activities_insert = array(
'cid' => $class_insert_id,
'act1' => $_POST['classact'][0],
'act2' => $_POST['classact'][1],
'act3' => $_POST['classact'][2]
);
$activities_insert_id = my_insert('class_act', $activities_insert);
There sure is enough room for improvement and optimization - just wanted to show you how awesome PHP can be :-P

Related

How to add three values into a database in a single foreach loop, using PHP?

I have an input form with two values as a key, constructed this way:
<input name="verificarPago['.$x['pagoID'].'-'.$x['userID'].']" type="text">
So, the HTML would look like, for example, like this:
<input name="verificarPago[4-10]" type="text">
Besides that I have the value that the user can type, for example "Juan".
The inputs are created programmatically, and I want to save them each three values (in the example: 4, 10, Juan) into a database.
So, when the user submits the form, I thought on using foreach in order to access the elements in that array, but my problem is: How may I explode the keys to access the two values separately?
I've tried this (I'm not taking into account security now, I'm trying to prove the concept):
$verificar = $_POST['verificarPago'];
foreach ($verificar as $pago => $curso) {
//I'm pretty much stuck here.
$verificar= array_flip(explode("-", $verificar));
//I want to insert the three items into the database
$verificarPago = "INSERT pagosVerificados SET userID = '$usuario', pagoID = '$pago', cursoID = '$curso'";
$cargarPago = mysqli_query($conectar, $verificarPago);
}
I've tried adding to the form another input type, so the values wouldn't be together, but that way I should do a foreach inside a foreach and that renders duplicated results (and with errors as well).
Without addressing any architectural issues, adding error-checking, or addressing security problems, here's how to do what you're asking for
$verificar = $_POST['verificarPago'];
foreach ($verificar as $ids => $text) {
list($pagoID, $cursoID) = explode("-", $ids);
$sql = "INSERT INTO pagosVerificados (userID, pagoID, cursoID, someVarcharField)
VALUES ($usuario, $pagoID, $cursoID, '$text');";
$cargarPago = mysqli_query($conectar, $sql);
}
This is a tad inefficient though - executing an insert for every iteration. Since mysql supports bulk inserts, you can modify the generation of the query to leverage that.
$verificar = $_POST['verificarPago'];
$rows = array();
foreach ($verificar as $ids => $text) {
list($pagoID, $cursoID) = explode("-", $ids);
$rows[] = "($usuario, $pagoID, $cursoID, '$text')";
}
$sql = "INSERT INTO pagosVerificados (userID, pagoID, cursoID, someVarcharField) VALUES "
. implode(',', $rows)
. ";";
$cargarPago = mysqli_query($conectar, $sql);
Now it's just one round-trip to the database
This is a bizarre way of passing values over POST. But, to expand on Peter's answer and address the glaring security issues, you can also use prepared statements. They're designed to be prepared once and then executed multiple times so are perfect for the job.
$verificar = $_POST['verificarPago'];
$sql = "INSERT INTO pagosVerificados (userID, pagoID, cursoID, someVarcharField) VALUES (?, ?, ?, ?)"
$stmt = $conectar->prepare($sql);
foreach ($verificar as $ids => $text) {
list($pagoID, $cursoID) = explode("-", $ids);
$stmt->bindParam("iiis", $usuario, $pagoID, $cursoID, $text);
$stmt->execute();
}
It's been years since I've worked with mysqli, but this should do the trick. You'll want to include some error checking in there as well.

Shorter way of inserting form data into database?

I have a form that returns all of the below data
$name = $_POST['name'];
$description = $_POST['description'];
$type = $_POST['type'];
$env1 = $_POST['environment[com1]'];
$env2 = $_POST['environment[com2]'];
$env3 = $_POST['environment[com3]'];
$hltCode = $_POST['hlType[code]'];
$hltDB = $_POST['hlType[db]'];
$hltWCF = $_POST['hlType[wcf]'];
$tfsID = $_POST['tfsID'];
$release = $_POST['release'];
$createdBy = 'mhopkins';
$updatedBy = 'mhopkins';
This of course leads to a VERY long query like the following
$insertQuery = "INSERT INTO patches (name, description, type, com1, com2, bofa, code, db, wcf, tfsID, release, createdBy, updatedBy) VALUES ('".$name."','".$description."''".$type."','".$envCom1."','".$envCom2."','".$envBofA."','".$hltCode."','".$hltDB."','".$hltWCF."','".$tfsID."','".$release."','".$createdBy."','".$updatedBy."'")
$insertResult = $link->query($insertQuery);
The values section has a LOT of punctuation and many possibilities for typos. If I have my variable names be the same as the field columns, is there an easier/shorter way to do this?
Your code has sql injection vulnerabilities, I wouldn't run that code even from a trusted source.
You can try using an ORM like Idiorm, it will manage the column names and escape variables for you https://idiorm.readthedocs.org/en/latest/models.html?highlight=insert https://github.com/j4mie/idiorm/
require_once 'idiorm.php';
ORM::configure(array(
'connection_string' => 'mysql:host=localhost;dbname=my_database',
'username' => 'database_user',
'password' => 'top_secret'
));
$patch = ORM::for_table('patches')->create($_POST);
$patch->createdBy = 'mhopkins';
$patch->updatedBy = 'mhopkins';
$patch->save();
You could try to use variables to get the data out of $_POST and reuse them in the SQL string.
Like:
<?php
$descriptionFieldName = "description";
$description = $_POST[$descriptionFieldName];
$sql = "INSERT INTO patches ($descriptionFieldName) VALUES ($description);
?>
Not much shorter, well, even longer. Though this way you are only typing the form input name and the SQL column name once.
You can also try mapping an array to do the job for you, something like:
$dbColumnsToValues = array(
'column_1' => $_POST['column1'],
'column_2' => $_POST['column2'],
);
$columns = "'" . implode("',", array_keys($dbColumnsToValues)) . "'";
$values = "'" . implode("',", array_map(array($link, 'escape'), array_values($dbColumnsToValues))) . "'";
$sql = "INSERT INTO `some_table` (".$columns.") VALUES(".$values.")";
Not tested though, but you should get the point.
Also, assuming your $link object has an escape method that will make sure your input won't trigger an sql injection.
Lets assume that you have a table consisting of 3 columns: col0, col1, col2.
If you are inserting all the fields that are present in the table and in the same order, you can omit listing the column names in the query. Like instead of
INSERT INTO `table` (`col0`, `col1`, `col2`) VALUES ("{$val0}", "{$val1}", "{$val2}",);
try
INSERT INTO `table` VALUES ("{$val0}", "{$val1}", "{$val2}");
PS: PLease sanitize the variable values before using them in the query.

Insert multiple same named fields into MySQL Database using PHP

I have multiple fields with names that look like name_$i and I am trying to figure out a way to "on submit", send them all to the database. The thing is that the form is looped and the insert has to be able to adapt to the number of fields in the form. Is there a way to do this???
<?php
$fldcnt = $_POST['fldcnt'];
$i = $_POST['i'];
for ($i = 0; $i < $fldcnt; $i++){
$NAME = $_POST['name_$i'];
$AGE = $_POST['age_$i'];
$ADDRESS = $_POST['address_$i'];
$TELEPHONE = $_POST['telephone_$i'];
$EMAIL = $_POST['email_$i'];
$q_register_new_users = "insert into registration set
NAME = '$NAME',
AGE = '$AGE',
ADDRESS = '$ADDRESS',
TELEPHONE = '$TELEPHONE',
EMAIL = '$EMAIL'";
mysql_query($q_new_products,$connection) or die(mysql_error());
};
?>"
HTML and PHP
You can enter input fields into an array by simply calling the field name[]. Like so:
<input name="name[]" />
You can then use PHP to loop through the fields like so:
foreach($_POST['name'] as $key=>$value){
// Insert the value of the form field into a string or query
// i.e. build the query
$query .= $value;
}
// Then execute the query for each set of fields
The logic above is actually incorrect, but it should give you an idea of what I mean.
MySQL
Your SQL syntax is incorrect, the correct syntax for inserting into a MySQL database is:
INSERT INTO `table` (`field_1`, `field_2`)
VALUES ('value_1', 'value_2')
PLEASE NOTE
The use of the mysql_ functions is hugely discouraged due to there impending deprecation. Instead, most PHP programmers are now using the PDO / SQLite Classes. Whilst these might seem complex, they are actually pretty simple and offer a much more secure way of executing SQL statements.
PDO
SQLite
The syntax for INSERT statement should be like this,
INSERT INTO registration (NAME , AGE , ADDRESS, TELEPHONE, EMAIL)
VALUES ('$NAME', '$AGE', '$ADDRESS','$TELEPHONE', '$EMAIL')
but hte query above is vulnerable with SQL INJECTION, please read the article below to learn how to protect from it,
How can I prevent SQL injection in PHP?
If you are going to keep structure of your code, you need to use double quotes instead of apostrophes
$NAME = $_POST["name_$i"];
or put the variable out
$NAME = $_POST['name_'.$i];
Using array is best way to do this. But if you still want to go head with a counter then you could use
for($i = 0;isset($_POST["name_{$i}"]);$i++)
{
// name found
}
Please note that this code may not be optimal if the name_xx fields are coming from checkboxes, where a user selected items and skipped some in between.
PS. I posted this a comment but it is more suitable as an answer.

Inserting form values with spaces into mysql 4.1

I'm trying to insert form data into a MySQL 4.1 DB. The problem I'm having is form fields that include spaces get truncated before insertion. The POST variables are complete, spaces and all. Just being cut off somewhere. For instance, "South Lake Tahoe" is inserted simply as "South". Zip codes and telephone numbers with dashes are also fine. The site I'm working on is hosted by Yahoo Small Business, and they're still using MySQL 4.1. I don't know if that is the problem, but I do know I never had issues doing this with MySQL 5+. The user fills out a form to add a new member. Upon Submit, the form data is POSTED to another page for processing:
$k = array();
$v = array();
$first_name = $_POST['first_name'];
$last_name = $_POST['last_name'];
$result = mysql_query("SELECT * FROM members WHERE first_name='$first_name' AND last_name='$last_name'");
if(mysql_num_rows($result)>0){
mysql_free_result($result);
exit("Duplicate User in Database");
}
mysql_free_result($result);
array_pop($_POST);//Don't need the Submit value
foreach($_POST as $key=>$value){
array_push($k, "$key");
array_push($v, "$value");
}
$fields = implode(", ", $k);
$values = array();
foreach($v as $key=>$value){
array_push($values, '"'.$value.'"');
}
$values_string = implode(", ", $values);
$result = mysql_query("INSERT INTO members($fields) VALUES($values_string)");
I'm sure there are better ways of doing this, but I'm still on the way up the learning curve. Please point out any obvious flaws in my thinking.
Any suggestions are greatly appreciated.
EDIT: The field types in MySQL are correct and long enough. For example, the field for City is set as VARCHAR(30).
Thanks much,
Mark
This code is horrifically insecure - you're taking user-supplied values and plopping them directly into your SQL statements without any sanitization. You should call http://php.net/manual/en/function.mysql-real-escape-string.php on anything you insert into a query this way (parameterized queries with PDO are even better).
You also make some assumptions, such as $_POST always being ordered a certain way (is that guaranteed?) and that you have exactly as many elements in your form as you have fields in your table, and that they're named identically. The code as it's written is the kind of thing a lot of beginning programmers do - it feels efficient, right? But in the end it's a bad idea. Just be explicit and list out the fields - e.g.
$field1 = $_POST['field1'];
$field2 = $_POST['field2'];
$sql = "insert into mytable (field1, field2) values ('" . mysql_real_escape_string($field1) . "', '" . mysql_real_escape_string(field2) . "')";
mysql_query($sql);
I haven't touched on why stuff would cut off at the first space, as this would imply that your code as you have it presented is salvageable. It's not. I get the feeling that reworking it as I described above might make that problem go away.
<?php
// Remember to always escape user input before you use them in queries.
$first_name = mysql_real_escape_string($_POST['first_name']);
$last_name = mysql_real_escape_string($_POST['last_name']);
$result = mysql_query("SELECT * FROM members WHERE first_name='$first_name' AND last_name='$last_name'");
if (mysql_num_rows($result) > 0) {
mysql_free_result($result);
exit("Duplicate User in Database");
}
mysql_free_result($result);
// I removed your loop around $_POST as it was a security risk,
// and could also become non-working. (What would happen if the order
// of the $_POST keys were changed?)
// Also the code become clearer this way.
$result = mysql_query("INSERT INTO members(first_name, last_name) VALUES('$first_name', '$last_name')");

Problem constructing an array for an SQL query

I have a 1 dimensional array of strings ($answers). I want to store each string as a new record a long with an itemId (the same itemId for each answer) into my table "answers_tb".
I have tried.....
using a foreach to construct a new array 2 dimensional array, with the $answers array and the itemID and then imploding this new array into my query.
not working.
i get this error:
Column count doesn't match value count at row 1
here is my code:
$records = array();
foreach($answers as $item_id => $text_value) {
$records[] = '("' . $item_id . '","' . $text_value . '")';
}
$sql = "INSERT INTO answers_tb (item_id, text_value) VALUES('" . implode(',', $records)." ')";
mysql_query($sql) or die(mysql_error());
many thanks for getting this far, even if you cant help.
regards,
Aside from particular problem, just to teach you a lesson.
You are working on your task in wrong way, upside down.
To put it straight, you're writing a program that builds some text.
So, first of all, it would be extremely handy to know, what particular text you want to get as a result. Thus, you have to write desired SQL query by hand and run in SQL console to see if it works okay or has any errors. If you experience any problem on this stage, you may ask under mysql tag, what query you need.
The rest is going to be easy. Upon finishing your program just print it's result out, and compare with example you've got before. Then correct your code to make them match. Repeat.
Done.
Always do your job this way and you will have no problem.
This should work:
$records = array ();
$itemid = 3; // or any arbitrary value
foreach ($answers as $text_value) {
$records[] = '("' . $itemid . '","' . $text_value . '")';
}
$sql = "INSERT INTO answers_tb (item_id, text_value) VALUES " . implode(',', $records);
mysql_query ($sql)
or die (mysql_error ());
With your current solution you create a query like:
INSERT INTO answers_tb (item_id, text_value) VALUES (('1', 'asd'),('2', 'bsd'))
It shoould look like:
INSERT INTO answers_tb (item_id, text_value) VALUES ('1', 'asd'),('2', 'bsd')
So you don't need the extra parens.

Categories