Execute Multiple MySQL Queries using PDO from PHP Post - php

I have a PHP script to post the following data to add-rma-process.php after submission:
$_POST['rmanumber']
$_POST['parent']
$_POST['qty']
However, there are also other fields which are to be posted but will depend on the $_POST['qty'] variable. Say, the $_POST['qty'] = 5 then I will have $_POST['pn1'], $_POST['sn1'], $_POST['rm1'] up to $_POST['pn5'], $_POST['sn5'], $_POST['rm5']. I think you guys get the logic.
Once add-rma-process.php receives these data, I am doing this:
require("common.php");
for($i=0; $i<$_POST['qty']; $i++) {
$count = $i+1; // to start with 1 instead of 0
$query = "INSERT INTO rmadb (rmanumber, parent, childpn, childsn, remarks, user, date) VALUES (:rmanumber, :parent, :childpn, :childsn, :remarks, :user, NOW())";
$query_params = array(
":rmanumber" => $_POST['rmanumber'],
":parent" => $_POST['parent'],
":childpn" => $_POST['pn$count'],
":childsn" => $_POST['sn$count'],
":remarks" => $_POST['rm$count'],
":user" => $_SESSION['user']['fname']." ".$_SESSION['user']['lname']
);
try {
$stmt = $db->prepare($query);
$res = $stmt->execute($query_params);
} catch(PDOException $ex) {
die("Failed to run query: " . $ex->getMessage());
}
}
What I was trying to do is do a for loop to execute the query until the condition is met but it is not working. What seems to be wrong?

You should use double quotes here so that key can be evaluated
$_POST["pn$count"]
^ ^
You don't need to introduce $count variable. Change condition in for
You should prepare your query once and then execute it multiple times with different parameters. That's the whole point behind prepared statements. Preventing sql injections is just a beautiful side effect.
That being said your might look something like this
require("common.php");
$query = "INSERT INTO rmadb (rmanumber, parent, childpn, childsn, remarks, user, date) VALUES (:rmanumber, :parent, :childpn, :childsn, :remarks, :user, NOW())";
$stmt = $db->prepare($query);
for ($i = 1; $i <= $_POST['qty']; $i++) {
$query_params = array(
":rmanumber" => $_POST['rmanumber'],
":parent" => $_POST['parent'],
":childpn" => $_POST["pn$i"],
":childsn" => $_POST["sn$i"],
":remarks" => $_POST["rm$i"],
":user" => $_SESSION['user']['fname']." ".$_SESSION['user']['lname']
);
$res = $stmt->execute($query_params);
}

Anytime you see yourself naming inputs like rm1, rm2, etc. know that that this is a clear anti-pattern. You should be using array access notation for your input names like:
<input name="rm[]" ... />
PHP will automatically take all inputs with same name and compile into an array that is available in $_POST - so $POST['rm'] and so forth.
This would simplify you loop to something like
$count = $_POST['qty']; // not shown you probably want to validate this value before using it
for ($i = 0; $i < $count; $i++) {
$query_params = array(
":rmanumber" => $_POST['rmanumber'],
":parent" => $_POST['parent'],
":childpn" => $_POST['pn'][$i],
":childsn" => $_POST['sn'][$i],
":remarks" => $_POST['rm'][$i],
":user" => $_SESSION['user']['fname']." ".$_SESSION['user']['lname']
);
$res = $stmt->execute($query_params);
}
Note that since I am guessing you are using some kind of javascript in your form to create X number of input fields based on the value in qty, this saves you a lot of headache in javascript in trying to number each input field. You can easily just clone the same input field (or template for the input field) and insert it into the DOM X times without the need to individually change it's one's name property.

Related

How to INSERT simultaneously two different arrays in PDO MySQL?

I'm having trouble with a PDO insert.
I'd like to insert a multidimensional array into a db, which i managed to.
However, i also would like to insert a completely different array, disconnected from the first one into the same db line (which means same INSERT query).
1st multidimensional array = $_POST['training']
2nd array = $training_diploma
Kinda difficult to explain. Here is the code :
$id = "1";
$training_diploma = ("master", "bachelor");
$id_training_key = $id_training_key = $id.'_'.$training_diploma; (return: 1_master)
$sql = "INSERT INTO users_resumes (id,resume_category,id_training_key,training_diploma,training_school,training_level,training_start_date,training_end_date) VALUES ($id,'Training',$id_training_key,:training_diploma,:training_school,:training_level,:training_start_date,:training_end_date)";
$stmt= $pdo->prepare($sql);
foreach($_POST['training'] as $params){
$stmt->execute($params);
}
Any help is very welcome !!! Thx a looot !
You need to iterate the $training_diploma array as well as the $_POST array. It would be better to also include the id and id_training_key as parameters in your query so you don't have to prepare a new query for each set of values:
$id = "1";
$training_diploma = array("master", "bachelor");
$sql = "INSERT INTO users_resumes (id,resume_category,id_training_key,training_diploma,training_school,training_level,training_start_date,training_end_date) VALUES (:id,'Training',:id_training_key,:training_diploma,:training_school,:training_level,:training_start_date,:training_end_date)";
$stmt= $pdo->prepare($sql);
foreach($_POST['training'] as $params) {
foreach ($training_diploma as $diploma) {
$stmt->execute(array_merge($params, array('id' => $id, 'id_training_key' => $id . '_' . $diploma)));
}
}

I'm Unable to perform a PHP insert query

I'm trying to insert the data in a MYSQL database but it seems that my query is not working i've tried all other methods but nothing is working for me ,Here is the PHP that i'm using
<?php
$server="localhost";
$database="hospital";
$login="root";
$password="";
$connexion=mysql_connect ($server, $login, $password) or die ('Server cannot be found'.mysql_error ( ));
mysql_select_db ($database,$connexion)or die ('database cannot be found'.mysql_error( ));
$a= mysql_real_escape_string($_POST['doctorname']);
$b = mysql_real_escape_string($_POST['writtendate']);
$c = mysql_real_escape_string($_POST['hospitalname']);
$d = mysql_real_escape_string($_POST['patientname']);
$e = mysql_real_escape_string($_POST['dateofbirth']);
$f= mysql_real_escape_string($_POST['cardnumber']);
$g = mysql_real_escape_string($_POST['groupname']);
$h = mysql_real_escape_string($_POST['drug1']);
$i = mysql_real_escape_string($_POST['drug2']);
$j = mysql_real_escape_string($_POST['drug3']);
$k = mysql_real_escape_string($_POST['drug4']);
$l = mysql_real_escape_string($_POST['amount1']);
$m = mysql_real_escape_string($_POST['amount2']);
$n = mysql_real_escape_string($_POST['amount3']);
$f = mysql_real_escape_string($_POST['principalmembersname']);
if(#$_POST['submit'])
{
$query="insert into uap(doctorname,writtendate,hospitalname,patientname,dateofbirth,cardnumber,groupname,principalmembersname,drug1,drug2,drug3,drug4,amount1,amount2,amount3) values ('$_POST[doctorname]','$_POST[writtendate]','$_POST[hospitalname]','$_POST[patientname]','$_POST[dateofbirth]','$_POST[cardnumber]','$_POST[groupname]','$_POST[principalmembersname]','$_POST[drug1]','$_POST[drug2]','$_POST[drug3]','$_POST[drug4]','$_POST[amount1]','$_POST[amount2]','$_POST[amount3]')";
$answer=mysql_db_query ($database, $query);
}
mysql_close ($connexion);
?>
To get you on the right track on using PDO and prepared statements (with named placeholders in this case):
<?php
$pdo = new PDO('mysql:host=localhost;dbname=databasename', 'username', 'password');
$statement = $pdo->prepare("INSERT INTO `uap` (`doctorname`,`writtendate`,`hospitalname`,`patientname`,`dateofbirth`,`cardnumber`,`groupname`,`principalmembersname`,`drug1`,`drug2`,`drug3`,`drug4`,`amount1`,`amount2`,`amount3`) VALUES (:doctorname, :writtendate, :hospitalname, :patientname, :dateofbirth, :cardnumber, :groupname, :principalmembersname, :drug1, :drug2, :drug3, :drug4, :amount1, :amount2, :amount3)");
$result = $statement->execute(
array(
'doctorname' => $_POST['doctorname'],
'writtendate' => $_POST['writtendate'],
'hospitalname' => $_POST['hospitalname'],
'patientname' => $_POST['patientname'],
'dateofbirth' => $_POST['dateofbirth'],
'cardnumber' => $_POST['cardnumber'],
'groupname' => $_POST['groupname'],
'principalmembersname' => $_POST['principalmembersname'],
'drug1' => $_POST['drug1'],
'drug2' => $_POST['drug2'],
'drug3' => $_POST['drug3'],
'drug4' => $_POST['drug4'],
'amount1' => $_POST['amount1'],
'amount2' => $_POST['amount2'],
'amount3' => $_POST['amount3']
)
);
if (!$result)
{
echo "SQL Error <br/>";
echo $statement->queryString."<br/>";
echo $statement->errorInfo()[2];
}
Although I still think your schema could use some optimization (eg. a dedicated drug table with a many-to-many relation to patients or whatever this is)
The problem with the code that you have above mainly lies in string concatenation. In your $query variable you have two primary issues:
First you have combined array syntax within a quoted string:
$query = "insert into uap (...) values ('$_POST[doctorname]')"
Second the when you reference arrays like $_POST[doctorname] (without the quotes around the keys) PHP assumes that the unquoted string is a constant that contains the same value as its name. That makes this seem like proper code, but it is actually very, VERY messy.
The PHP interpreter cannot understand exactly what you are trying to do in this case and ends up stopping concatenation at the $_POST variable. So your resultant string probably looks something like this: insert into uap (...) values ('array[doctorname]'). You can correct this by using braces to tell the PHP interpreter to use the whole array syntax in the string:
$query = "insert into uap (...) values ('{$_POST['doctorname']}')" or by using the concatenation . operator to perform proper string concatenation: $query = 'insert into uap (...) values ('".$_POST['doctorname']."')".
You simplest solution however, is to use the variables that you had specified above in your code. You final $query variable should look something like this (which will also use the `mysql_escape_string() function that you used above):
<?php
$server="localhost";
$database="hospital";
$login="root";
$password="";
$connexion=mysql_connect ($server, $login, $password) or die ('Server cannot be found'.mysql_error ( ));
mysql_select_db ($database,$connexion)or die ('database cannot be found'.mysql_error( ));
$doctorname = mysql_real_escape_string($_POST['doctorname']);
$writtendate = mysql_real_escape_string($_POST['writtendate']);
$hospitalname = mysql_real_escape_string($_POST['hospitalname']);
$patientname = mysql_real_escape_string($_POST['patientname']);
$datofbirth = mysql_real_escape_string($_POST['dateofbirth']);
$cardnumber = mysql_real_escape_string($_POST['cardnumber']);
$groupname = mysql_real_escape_string($_POST['groupname']);
$drug1 = mysql_real_escape_string($_POST['drug1']);
$drug2 = mysql_real_escape_string($_POST['drug2']);
$drug3 = mysql_real_escape_string($_POST['drug3']);
$drug4 = mysql_real_escape_string($_POST['drug4']);
$amount1 = mysql_real_escape_string($_POST['amount1']);
$amount2 = mysql_real_escape_string($_POST['amount2']);
$amount3 = mysql_real_escape_string($_POST['amount3']);
$principlemembersname = mysql_real_escape_string($_POST['principalmembersname']);
if(#$_POST['submit'])
{
$query = "insert into uap(doctorname,writtendate,hospitalname,patientname,dateofbirth,cardnumber,groupname,principalmembersname,drug1,drug2,drug3,drug4,amount1,amount2,amount3)
values ('$doctorname','$writtendate','$hospitalname','$patientname','$datofbirth','$cardnumber','$groupname','$principlemembersname','$drug1','$drug2','$drug3','$drug4','$amount1','$amount2','$amount3')";
$answer=mysql_db_query ($database, $query);
}
mysql_close ($connexion);
?>
As noted by other users it would be a good idea to convert this code to use PDO and prepared statements as the mysql functions in PHP are deprecated.
Good luck! I hope this helps!

php Prepared Statement giving me JSON Malformed

My php code works fine when it is not a prepared statement - however when it is a prepared statement it is giving me a json malformed error. After debugging my code for some time I have realised that there is something wrong with my if statement and that it should be different when it is a prepared statement. I am not sure what to change but this is my code:
$statement = "SELECT userID, forename, surname, email, age FROM employees WHERE forename = ?"
$outcome = $conn -> prepare($statement);
$outcome->bind_param('s', $forename);
$outcome->execute();
$outcome->close();
$outcomearray = array();
echo json_encode("It works as of now"); // This bit works and the message is echoed
// From this point, it is giving me errors and problems
if(mysqli_num_rows($outcome)){
while($line = mysqli_fetch_assoc($outcome)){
$outcomearray[] = array
(
"userID" => $line["userID"],
"forename" => $line["forename"],
"surname" => $line["surname"],
"username" => $line["username"],
"email" => $line["email"],
"age" => $line["age"]
);
}
echo json_encode($outcomearray);
}
It is the following two lines:
if(mysqli_num_rows($outcome)){
while($line = mysqli_fetch_assoc($outcome)){
that I believe are giving the errors.
How do I fix this?
$stmt = $conn->prepare(
"SELECT userID, forename, surname, email, age FROM employees WHERE forename = ?"
);
$stmt->bind_param('s', $forename);
$stmt->execute();
$rows = array();
$result = $stmt->get_result();
while($line = $result->fetch_assoc()){
$rows[] = $line;
}
print json_encode($rows);
$conn->close();
Note that this is the typical pattern when you are returning JSON resonses. If there is no match you render an empty array - thus there is no real need to check the number of rows.
If you for whatever reason needed to you can get the number of rows from the num_rows property on the mysqli_result object:
$result = $stmt->get_result();
if ((bool) $result->num_rows) {
}
Also note that the whole point of fetch_assoc is to get an associative array. So if your column names line up with the JSON you want to produce there is no need to map the keys one by one.
http://php.net/manual/en/class.mysqli-result.php
Try use
$outcome->num_rows;
OR
mysqli_stmt_num_rows($outcome);
Also use
$outcome->bind_result('userID','email', 'age', 'surname', 'forename');
$outcome->fetch()
instead
mysqli_assoc_fetch()

php PDO insert batch multiple rows with placeholders

I am looking to do multiple inserts using PHP PDO.
The closest answer I have found is this one
how-to-insert-an-array-into-a-single-mysql-prepared-statement
However the example thats been given uses ?? instead of real placeholders.
I have looked at the examples on the PHP doc site for place holders
php.net pdo.prepared-statements
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
Now lets say I wanted to achieve the above but with an array
$valuesToInsert = array(
0 => array('name' => 'Robert', 'value' => 'some value'),
1 => array('name' -> 'Louise', 'value' => 'another value')
);
How would I go about it with PDO and multiple inserts per transaction?
I imagine it would start of with a loop?
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
foreach($valuesToInsert as $insertRow){
// now loop through each inner array to match binded values
foreach($insertRow as $column => value){
$stmt->bindParam(":{$column}", value);
}
}
$stmt->execute();
However the above does not work but hopefully will demonstrate what im trying to achieve
First of all, ? symbols are real place-holders (most drivers allow to use both syntaxes, positional and named place-holders). Secondly, prepared statements are nothing but a tool to inject raw input into SQL statements—the syntax of the SQL statement itself is unaffected. You already have all the elements you need:
How to insert multiple rows with a single query
How to generate SQL dynamically
How to use prepared statements with named place-holders.
It's fairly trivial to combine them all:
$sql = 'INSERT INTO table (memberID, programID) VALUES ';
$insertQuery = [];
$insertData = [];
$n = 0;
foreach ($data as $row) {
$insertQuery[] = '(:memberID' . $n . ', :programID' . $n . ')';
$insertData['memberID' . $n] = $memberid;
$insertData['programID' . $n] = $row;
$n++;
}
if (!empty($insertQuery)) {
$sql .= implode(', ', $insertQuery);
$stmt = $db->prepare($sql);
$stmt->execute($insertData);
}
I'm assuming you are using InnoDB so this answer is only valid for that engine (or any other transaction-capable engine, meaning MyISAM isn't included).
By default InnoDB runs in auto-commit mode. That means each query is treated as its own contained transaction.
To translate that to something us mortals can understand, it means that every INSERT query you issue will force hard-disk to commit it by confirming it wrote down the query information.
Considering how mechanical hard-disks are super slow since their input-output operation per second is low (if I'm not mistaken, the average is 300ish IO's), it means your 50 000 queries will be - well, super slow.
So what do you do? You commit all of your 50k queries in a single transaction. It might not be the best solution for various purposes but it'll be fast.
You do it like this:
$dbh->beginTransaction();
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
foreach($valuesToInsert as $insertRow)
{
// now loop through each inner array to match bound values
foreach($insertRow as $column => value)
{
$stmt->bindParam(":$column", value);
$stmt->execute();
}
}
$dbh->commit();
A little modifications in solution provided by N.B
$stmt->execute() should be outside of inner loop because you may have one or more columns that need to bind before calling $stmt->execute() else you 'll get exception "Invalid parameter number: number of bound variables does not match number of token".
2nd "value" variable were missing dollar signs.
function batchinsert($sql,$params){
try {
db->beginTransaction();
$stmt = db->prepare($sql);
foreach($params as $row)
{
// now loop through each inner array to match bound values
foreach($row as $column => $value)
{
$stmt->bindParam(":$column", $value);
}
$stmt->execute();
}
db->commit();
} catch(PDOExecption $e) {
$db->rollback();
}
}
Test:
$sql = "INSERT INTO `test`(`name`, `value`) VALUES (:name, :value)" ;
$data = array();
array_push($data, array('name'=>'Name1','value'=>'Value1'));
array_push($data, array('name'=>'Name2','value'=>'Value2'));
array_push($data, array('name'=>'Name3','value'=>'Value3'));
array_push($data, array('name'=>'Name4','value'=>'Value4'));
array_push($data, array('name'=>'Name5','value'=>'Value5'));
batchinsert($sql,$data);
Your code was actually ok, but had a problem in $stmt->bindParam(":$column", value); It should be $stmt->bindValue(":{$column}", $value); and it will work perfectly. This will assist others in future.
Full code:
foreach($params as $row)
{
// now loop through each inner array to match bound values
foreach($row as $column => $value)
{
$stmt->bindValue(":{$column}", $value); //EDIT
}
// Execute statement to add to transaction
$stmt->execute();
}
Move execute inside of the loop.
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
foreach($valuesToInsert as $insertRow)
{
$stmt->execute($insertRow);
}
If you experience any problems with this such recommended way, you have to ask a question, describing these certain problems.

How do I process an associative array properly in a PDO (or MySQLi) query?

I'm using MySQLi for a project (but could easily switch to PDO, read the edit at the bottom). What I want is to be able to process an associative array into an mysql query without typing every key/value pair manually. I know that might be simply put, but I'm still in a learning process when it comes to MySQLi/PDO. To make it clear what I mean here is an example:
Let's say I have this associative array:
$data = array(
'name' => 'Objective',
'short_name' => 'OB',
'generation' => 1
);
What I want is to create a query like this:
UPDATE signals SET ? = ? WHERE sid = '1'
And it to become a query like this (or instead of an UPDATE, an INSERT, SELECT etc.):
UPDATE signals SET
name = 'Objective',
short_name = 'OB',
generation = 1
WHERE sid = '1'
So basically my question is: is this possible with MySQLi or PDO itself? If it's possible how would I have to do this?
I've read on preparing statements before executing, but it's not getting to me yet. Hopefully someone can help me out.
Edit: I'm still very early into the project so i'm also fine with using PDO, but the same question remains. I did look into both PDO and mysqli, and I'm not sure how to do it with PDO either. So for the sake of the question i'll add PDO to as a tag and to the question.
Here is a function that will take an input array and produce something you can drop straight into your query, as long as you are only updating a single table:
function array_to_pdo_params($array) {
$temp = array();
foreach (array_keys($array) as $name) {
$temp[] = "`$name` = ?";
}
return implode(', ', $temp);
}
Now you can perform your PDO query like this:
// The data
$data = array(
'name' => 'Objective',
'short_name' => 'OB',
'generation' => 1
);
// The parameter for the WHERE clause
$sid = 1;
// Build the query string
$query = "
UPDATE `signals`
SET ".array_to_pdo_params($data)."
WHERE `sid` = ?
";
// Convert the data array to indexed and append the WHERE parameter(s) to it
$queryData = array_values($data);
$queryData[] = $sid;
$stmt = $db->prepare($query); // Obviously add the appropriate error handling
$stmt->execute($queryData);
You can use the PDO's execute statement by passing an array of input values, for a prepared query. For reference: http://php.net/manual/en/pdostatement.execute.php
Example:
<?php
/* Execute a prepared statement by passing an array of insert values */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->execute(array(':calories' => $calories, ':colour' => $colour));
?>
Zend_DB will let you do exactly that.
Tho we created a wrapper over it my work to make it simpler, I really think it's as simple as you can get, and it does all the magical stuff for you.
You really should give it a try; big time saver once you learn it.
How about building the query with http_build_query as follows:
$columns = array(
'name',
'short_name',
'generation', ...
);
$data = array(
'name' => 'Objective',
'short_name' => 'OB',
'generation' => 1
);
$to_update = array_intersect_key($data, array_flip($columns));
$update_string = urldecode(http_build_query(array_combine(array_keys($columns), array_fill(0, count($columns), '?')), '', ', '));
try {
$stmt = $db->prepare(sprintf('UPDATE table SET %s WHERE condition=?', $update_string));
$result = $stmt->execute(array_values($data));
...
} catch (\PDOException $ex) {
}
Be sure to have the parameter for the WHERE condition at the end of your $data array.

Categories