add multiple items to a database in one form - php

I've got an internal site I'm developing for work. I'm by no means a web developer but know enough to get some basic functionality done. I've got a form working fine for inserting data. I'm trying to figure out this one last piece, though.
The page is designed to add jobs to our site. Each position has assigned responsibilities. The easiest way to make this work (in my brain) is to create a table for responsibilities that has a responsibilityID, PositionID, and then the responsibility. I want a way to kind of bulk add these responsibilities when completing the form for the new position. Something similar to how you add new fields when using the MySQL workbench - where you can just click on the next row and it'll add that field. That would work great.
I'm not sure what to even search for to accomplish this other than adding multiple items - which hasn't turned up what I'm looking for.
Thanks in advance!

Most times people here like to see what you've tried.
This question was asked here.
example MySQL statement:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
You can replace the values with PHP variables if needed. Just make sure if they are strings, they are in 'quotes'.

If you have a form that allows you to submit multiple responsibilities simultaneously then I would use PDO. Remember PDO is your friend, and always sanitize your inputs before inserting them. Here is them most basic version, You probably want to replace the inputs with dropdowns or texteareas.
table
responsibilityID|PositionID|responsibility
The responsibilityID should be PK and auto-increment
html
<form>
<div>
<h1>job</h1>
<label>PositionID</label><input name='jobs[][positionID]' />
<label>responsability</label><input name='jobs[][responsibility]' />
</div>
<div>
<h1>job</h1>
<label>PositionID</label><input name='jobs[][positionID]' />
<label>responsability</label><input name='jobs[][responsibility]' />
</div>
<div>
<h1>job</h1>
<label>PositionID</label><input name='jobs[][positionID]' />
<label>responsability</label><input name='jobs[][responsibility]' />
</div>
<div>
<h1>job</h1>
<label>PositionID</label><input name='jobs[][positionID]' />
<label>responsability</label><input name='jobs[][responsibility]' />
</div>
<input type='submit' />
</form>
Basic
Create an insert statement then loop through your jobs binding each value to the statement and executing them.
$insert_sql = "INSERT INTO responsibilities (`PositionID`, `responsibility`) VALUES (:PositionID, :responsibility);";
$stmt = PDO::Prepare($insert_sql)
foreach ($jobs as $job){
//add some input testing before you execute to make sure you are not inserting bad values
$stmt->bindValue(":positionID", $job['positionID'], PDO::PARAM_INT);
$stmt->bindValue(":responsibility", $job['responsibility'], PDO::PARAM_STR);
$stmt->execute();
}
The :fieldname in the query tells PDO what needs to be replaced with the bind functions, then the bindValue/bindParam functions tells what to insert where into the query and properly escapes the value so you can insert it. Older sql functions allowed for unescaped or improperly escaped values and you got the little bobby tables problem. PDO protects you from some of the worst injection attacks, but you should probably make sure that positionID points to a real position or that responsibility doesn't have weird java-script exploit code in it.
Fancy
Create an insert statement, bind params, then foreach loop through your responsibilities, checking/sanitizing the input (never trust form data) then executing the statement. Every time you loop the bound parameter will point at the new job.
$insert_sql = "INSERT INTO responsibilities (`PositionID`, `responsibility`) VALUES (:PositionID, :responsibility);";
$job = array('positionID'=>NULL, 'responsibility'->NULL);
$stmt = PDO::Prepare($insert_sql)
$stmt->bindParam(":positionID", $job['positionID'], PDO::PARAM_INT);
$stmt->bindParam(":responsibility", $job['responsibility'], PDO::PARAM_STR);
foreach ($jobs as $job){
//add some input testing before you execute to make sure you are not inserting bad values
$stmt->execute();
}

with the inputs you want to have multi values, use the name attribute like responsibilities[], and then insert serialized data to the database

Related

Multiple Cells Not Updating into Mysql

Fairly new to php, please forgive me if my code is not eloquent.
I have a table/form with multiple rows/cells. Each cell is a drop down box. I've built this to UPDATE existing mysql-rows.
I'm having trouble figuring out how to press the submit button on the form and UPDATE all the mysql-rows. I've successfully updated mysql fields individually, but this is my first time trying to update multiple sql-rows at the same time.
In my front-end (let me know if you need me to post it), I run the below code to create a new increment variable for each -input type="submit" name="blah"...-
$namefieldname = 'name'.$i;
$positionfieldname = 'position'.$i;
$hoursdropdown = 'hours'.$i;
$overtimedropdown = 'overtime'.$i;
So name="blah" I write as name="'.$namefieldname.'" for example. I have a different form that uses this same $i concept to INSERT information and it works fine.
Below is the code that I'm not getting to work. This is what the -form action- goes to. The page processes without errors - but doesn't update mysql. I've double checked all names and everything is spelled correctly.
For now I've cut down the columns to try to get just this one column to update mysql.
<?php
include_once('toolbox.php');
//mysql connect info
$projectid = $_POST['projectid'];
$transcriberid = $_POST['transcriberid'];
for($i=0; $i<$staffcount; $i++) {
$positionfieldname = 'position'.$i;
//is a drop down of 5 choices
$thisposition = $_POST[$positionfieldname];
mysql_query("UPDATE transcribers SET transcriber_position='$thisposition' WHERE transcriber_id= '$transcriberid'");
}
header('Location: ./);
?>
First, you shouldn't use the mysql extension in new programs any more, because it is deprecated since version 5.5, and it was removed in PHP 7.0.0. Instead, use MySQLi or PDO_MySQL extension.
Second, it is important to handle user given data (e.g. from $_POST) appropriately before using them to concatenate sql statements. If the user gives a quote sign, he/she could alter your statement such as terminating it and update some other data in some other tables. If you use PDO_MySQL, function PDO::quote() can help you to prevent this:
$thisposition = $mysql_connection->quote($_POST[$positionfieldname]);
Even better is to use a prepared statement. It contains only placeholders where user provided data is used and the actual data is bound to this placeholders.
$stmt = $mysql_connection->prepare("UPDATE transcribers SET transcriber_position=:value");
$stmt->bindValue(':value', $transcriber_position, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
For updating multiple columns in a table, you can just list them, separated with comma, here an example:
mysql_query("UPDATE transcribers SET transcriber_position='$thisposition', transcriber_value=5 WHERE transcriber_id= '$transcriberid'");

can a mysqli injection affect the php script

So I have finished creating a database and I use php to insert data into it, I have been trying to do SQL injection attacks and other things to see if I am secure, but since I am no expert I was hoping to check that what I have done is secure and the correct way to go about.
I have this(names/variables have been modified) form and when the submit button is pressed, the function insert() runs
<form action="" method="POST">
var1: <input type="text" name="var1"><br>
var2: <input type="text" name="var2"><br>
<input type="submit" value="Submit">
</form>
<php?
function insert() {
$connect = mysqli_connect("localhost","user","user","table");
$var1 = $_POST['var1'];
$var2 = $_POST['var2'];
mysqli_query($connect, "INSERT INTO column_name (var1, var2) VALUES ( '$var1','$var2'); ");
}
?>
and I can't seem to inject my form which has var1 and var2 with this
$var2 = '): DROP TABLE test --and several variants of this
From looking around I have found that mysqli_query will only accept one query so that is why it is not working. Correct me if I am wrong.
my other idea was affecting the PHP script that is running,
by injecting the form with this
$var2 = "'); "); mysqli_query($connect,"DROP TABLE test");//
Question: can this type of thing happen? where you can affect the PHP function through the $post method while it runs? I have looked around and can't find anything. Is that because it can't?
any research papers, articles, etc. that I can have a look at to help if what I am asking is obvious would be appreciated :)
EDIT: I will be adding prepared Statements to make this secure
SQL injections use commands like union to run multiple queries at once at vulnerable place. Your form IS vulnerable, because you are either not using any sort of escaping, nor prepared statements. What if your $var2 would contain for example hi')? That would escape the brackets and open a vulnerability. Also if you just $_POST['value'] and insert it directly in database, it opens XSS vulnerability.
If you want to make sure your site is safe i suggest you:
Fisrt, Use prepare statement:
$mysqli->prepare("SELECT Distinct FROM City WHERE Name=?");
$stmt->bind_param("s", $city);
$stmt->execute();
Second, Use filter_input method, for example:
filter_input(INPUT_POST,'email',FILTER_EMAIL);
You are not supposed to certify your site against SQL Injection by trying to figure out how to exploit the hundreds of potential security breaches you leave all around the place.
If you want to make sure your site is safe, just take the applicable security measures, like using prepared statements.

how to insert multiple bids value in a coloumn [duplicate]

This question already has answers here:
Multiple inputs with same name through POST in php
(5 answers)
Closed 8 years ago.
I'm trying to insert multiple bids like from -to in a column 'bidamount'. I have did some coding in for database and some code I have did for multiple bids but what I'm getting here whenever I'm inserting the value like 3.1 to 8.1. It is inserting a value 8.1 and 0. This one is not inserting all the value from 3.1 to 8.1 in column bidamount in table of a database.
I'm new here in php so I'm not getting exact things what is wrong with these code. Please help me in this.
My code :
<?php
$con = mysql_connect("localhost","root","");
if(!$con) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db("gunjanbid", $con) or DIE('Database name is not available!');
if(isset($_POST['submit'])) {
$m=$_POST['bidamount'];
$n=$_POST['bidamount'];
for($bidd=$m;$bidd<=$n;$bidd++)
$bidds=array($bidd);
$username=$_SESSION['userName'];
$productid=$_GET['id'];
$sql1="INSERT INTO bid(productid,description,closing_date,bidamount,userName) values('$productid','$r',Now(),'$bidds','$username')";
$result1=mysql_query($sql1);
if($result1!=1) {
echo "failure!";
}
}
?>
<form action="" name="auction1" method="post" >
<input type="hidden" name="description" value="">
<input type="hidden" name="closing_date" value="">
<input type="text" name="bidamount" value="" size="5"> to
<input type="text" name="bidamount" value="" size="5" >
<input type="submit" name="submit" class="button" value="Bid Now">
</form>
Please help me. I'm new in php.
I suggest you to use this code
$bid = explode("to",$_POST['bidamount']);
$m = $bid[0];
$n = $bid[1];
instead of
$m = $_POST['bidamount'];
$n = $_POST['bidamount'];
Firstly: If you want to submit multiple values with the same name, you can put brackets after the name, like name="bidamount[]", and PHP will assemble them into an array for you.
Secondly, though, MySQL doesn't understand arrays. It doesn't like storing more than one value in a column. And quite frankly, you don't want to do it anyway. Seriously. It causes more trouble than it's worth.
Discrete values are harder to get. Since there's no "array" type in MySQL, you end up having to parse a string and other such junk to get your individual values back. Getting two values from two columns, on the other hand, is much simpler.
MySQL can't help you keep the data valid. All it sees is a big bunch of characters/bytes. It can't do but so much with the individual pieces. It can't enforce uniqueness, for example.
It makes indexes useless. Once you have to parse each string in order to find stuff in it, you've pretty much killed any chance of MySQL being able to use indexes to speed up the query.P
If your two values represent a "low" and "high", then call them that, and store them as separate fields.
If they're just two arbitrary amounts, on the other hand -- and particularly if you anticipate having more than two -- then they should each be part of their very own row in another table.
As for the code: though it's not part of the question, there are a couple of other issues.
mysql_query is deprecated. (Read: not even the authors of PHP think you should use it.) Stop farting around with it. There are much better ways of talking to a database.
You're trusting the user way too much.
Open up the page, then go into your browser's dev tools. find the hidden fields, and change the description to "Joe's item". Submit the form, and it should break. The reason is that SQL uses ' for quotes. One being in your string throws off the quoting and corrupts the SQL.
It's bad enough that this can be done accidentally -- but some people will do it on purpose, and can supply just the right data to trick your server into running SQL it shouldn't. That's called "SQL injection", and it can be a pretty serious security issue.
You could work around this issue by simply stripping ' out of your input. But frankly, that's almost as half-assed as just saying "Don't use apostrophes!!11!11". And there is at least one other special character in strings as well.
If you use a more modern database extension, like PDO, you can fix the first two issues at once.
Watch:
<?php
if ($_POST['submit']) {
// By the way, you don't need to create the DB connection if you don't need to
// mess with the DB. :)
$con = new PDO('mysql:host=localhost;dbname=gunjanbid', 'root', '');
$low = $_POST['low'];
$high = $_POST['high'];
$id = $_GET['id'];
$description = $_POST['description'];
$user = $_SESSION['username'];
// PDO has a `query` method that works much like `mysql_query`. But that does
// absolutely nothing to fix the SQL injection issue.
//
// Instead, use a prepared statement. You can insert placeholders (?) for data,
// and when you run the statement later with the real data, PDO and MySQL know which
// stuff is data and which is SQL. Since they're kept separate, the data won't have
// a chance to be interpreted as part of the SQL.
$stmt = $con->prepare('
INSERT INTO bid (productid, description, closing_date, userName, low, high)
VALUES (?, ?, NOW(), ?, ?, ?)
');
if (!$stmt->execute([$id, $description, $user, $low, $high])) {
echo 'Failure!';
}
}
?>

insert value of html select form into mysql database

I want to insert the value of a selected 'select form' into my mysql database.
How can i get the right value of this?
<form action='' method='post'>
<select name="myselectbox">
<option name="myoption1" value="myoption1">myoption1</option>
<option name="myoption2" value="myoption2">myoption2</option>
<option name="myoption3" value="myoption3">myoption3</option>
<option name="myoption4" value="myoption4">myoption4</option>
</select>
<input type='submit' value='submit'/>
</form>
something like that? (this one didn't work obviously..)
$sql = "INSERT INTO Entries (myoption1) VALUES ('$_POST[myselectbox]')";
you have to wrap your select tag into a form tag .
<form action='' method='post'>
<select name="myselectbox">
<option name="myoption1" value="myoption1">myoption1</option>
<option name="myoption2" value="myoption2">myoption2</option>
<option name="myoption3" value="myoption3">myoption3</option>
<option name="myoption4" value="myoption4">myoption4</option>
</select>
<input type='submit' value='submit'/>
</form>
once you submit the form, you will get the post variable as $_POST['myselectbox'] that could be appended into a mysql query as you have already did. but for a better way dont just append it like that but check the form is submitted and post variables are available or not before appending.
eg:
if(!empty($_POST['myselectbox'])){
/*.. do your query section... */
}
you have error in your SQL command, $_POST needs html names to be wrapped in quotes like => $_POST['some_name'] :
$sql = "INSERT INTO Entries (myoption1) VALUES ('$_POST[myselectbox]')";
/* ^^ missing quotes here*/
try it this way :
$sql = "INSERT INTO Entries (myoption1) VALUES (".$_POST['myselectbox'].")";
Assuming that your form is correct and it is posting the values that you want to your script.
(You have sprinkled your code with echo to ensure this is the case?)
The simplest reliable way of sending the data into a SQL statement and therefore into mysql is to use prepared statements.
Take a look here: http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
Basically you write the SQL statement without your variables in it (replaced with ?) and then tell mysql to execute the statements with your variables later. It avoids the need to escape strings and worry about how to build things up.
As an example, you might have:
// Connect to mysql
$mysqli = new mysqli('where your server is', 'my_user', 'my_password', 'world');
// Build the initial statement - easier to read as you don't have your string concatenation here
$stmt = $mysqli->prepare( "INSERT INTO Entries (myoption1) VALUES (?)" );
// Tell mysql that the '?' should be replaced with the value in your post array
$stmt->bind_param( "s", $POST['myselectbox'] );
// Execute the statement
$stmt->execute()
Obviously you should add error handling too, but the documentation covers the basics of this.
SQL Injection
The main reason why the use of prepared statements is a good idea is that it avoids SQL injection attacks.
There are other ways round, but in my mind this is the simplest solution.
SQL Injection attacks are situations where someone attempts to change the SQL statement that is being run by "injecting" other SQL into your statement.
Using your code as an example, you may execute this statement:
$sql = "INSERT INTO Entries (myoption1) VALUES ('". $_POST['myselectbox'] ."')";
Which would normally receive (let's suggest) something like myoption1.
This would result in the SQL being:
INSERT INTO Entries (myoption1) VALUES ('myoption1');
If someone decided to, they could send '='' OR '1'='1
This would result in the SQL being:
INSERT INTO Entries (myoption1) VALUES (''='' OR '1'='1');
Which is (obviously) very different.
Or, even worse send '=')'; DROP TABLE Entries WHERE (''='
This would result in the SQL being:
INSERT INTO Entries (myoption1) VALUES (''=''); DROP TABLE Entries WHERE (''='');
Use Prepared Statements
Simply put, but using prepared statements, you are telling mysql that what you are sending is a literal string to be used as a parameter. It can never be regarded as part of the statement itself and therefore the above is simply not possible.
Much much safer.
I hope that makes it clearer. If you want more info I suggest you research it independently...
$value = mysql_real_escape_string($_POST['myselectbox']);
$sql = "INSERT INTO Entries (myoption1) VALUES ($value)";

UPDATE only provided fields in MySQL table using PHP

I have a user table with and id field and 10 other fields storing user details of various types that the user can change via various web forms. I want to have a PHP script that gets POSTed changed values for some subset of these fields, and UPDATEs only those fields that are received in the POST data. I'm finding this surprisingly difficult to do in a way that doesn't suck. We use mysqli for all database interaction in the rest of this application so mysqli-based solutions are strongly preferred.
The options I've considered and dismissed so far:
1) Run a separate UPDATE query for every field provided in the POST data - yuck, I don't want to hit the database up to 10 times for something that could be done in one query.
2) Have a dictionary mapping field names to the fields' data types, and iteratively construct the query by looping through the provided fields, checking whether they are text fields or not, calling mysqli_real_escape_string on the string fields and otherwise sanitizing the others (e.g. by type checking or sprintf with '%i' placeholders). - Yuck! I could probably safely do things this way if I was careful, but I don't want to make a habit of using this kind of approach because if I'm careless I'll leave myself open to SQL injection. Parameterized queries don't give me the potential to screw up dangerously, but this approach does. My ideal is to never concatenate any data into an SQL query manually and always rely upon parameterized queries; the database libraries of other languages, like Python, let me easily do this.
3) Use a parameterized query - this is my ideal for everything, since as long as I insert all externally-provided data into my query via the bind_param method of a mysqli statement object, I'm immune to SQL injection and don't have to worry about sanitization, but using parameterized queries seems to be impossible here. The trouble is that bind_param requires that the data be passed as variables, since all arguments after the first are passed by reference. I can reasonably elegantly iteratively construct a query with ? placeholders, and while I'm at it construct the string of types that gets passed as the first argument to bind_param ('ssiddsi' etc.), but then there's no way I can see to choose at runtime which of my 10 fields I pass to bind_params (unless I have a switch statement with 10^2 cases).
Is there some PHP language construct I'm missing (something similar to array unpacking) that will allow me to choose at runtime which variables to pass as arguments to bind_param? Or is there some other approach I haven't considered that will let me solve this simple problem cleanly and safely?
You can easily combine 2 and 3 by means of my SafeMySQL library.
The code will look like
$allowed = array('title','url','body','rating','term','type');
$data = $db->filterArray($_POST,$allowed);
$sql = "UPDATE table SET ?u WHERE id=?i";
$db->query($sql, $data, $_POST['id']);
note that $allowed array doesn't make all these fields necessarily updated - it just filters POST fields out. So, even $_POST with only id and url would be correctly updated.
Nevertheless, using prepared statements, although toilsome, also quite possible.
See the code below
public function update($data, $table, $where) {
$data_str = '' ;
foreach ($data as $column => $value) {
//append comma each time after first item
if (!empty($data_str)) $data_str .= ', ' ;
$data_str .= "$column = $value" ;
}
$sql = "UPDATE $table SET $data_str WHERE $where";
mysqli_query($sql) or die(mysqli_error());
return true;
}
$data is an array, in your case it's $_POST.
If you want to be more specific about the data to be saved from $_POST array, you can define an array of allowed columns. For example,
$allowed = array('id', 'username', 'email', 'password');
By doing this, you can filter your $_POST array and pass it to update() function.

Categories